/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.onosproject.cord.gui;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
import org.onosproject.cord.gui.model.Bundle;
import org.onosproject.cord.gui.model.BundleDescriptor;
import org.onosproject.cord.gui.model.BundleFactory;
import org.onosproject.cord.gui.model.JsonFactory;
import org.onosproject.cord.gui.model.SubscriberUser;
import org.onosproject.cord.gui.model.UserFactory;
import org.onosproject.cord.gui.model.XosFunction;
import org.onosproject.cord.gui.model.XosFunctionDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.cord.gui.model.XosFunctionDescriptor.URL_FILTER;

/**
 * In memory cache of the model of the subscriber's account.
 */
public class CordModelCache extends JsonFactory {

    private static final String KEY_SSID_MAP = "ssidmap";
    private static final String KEY_SSID = "service_specific_id";
    private static final String KEY_SUB_ID = "subscriber_id";

    private static final int DEMO_SSID = 1234;

    private static final String EMAIL_0 = "john@smith.org";
    private static final String EMAIL_1 = "john@doe.org";

    private static final String EMAIL = "email";
    private static final String SSID = "ssid";
    private static final String SUB_ID = "subId";

    private static final String BUNDLE = "bundle";
    private static final String USERS = "users";
    private static final String LEVEL = "level";
    private static final String LOGOUT = "logout";

    private static final Map<Integer, Integer> LOOKUP = new HashMap<>();

    private String email = null;
    private int subscriberId;
    private int ssid;
    private Bundle currentBundle;

    private final Logger log = LoggerFactory.getLogger(getClass());

    // NOTE: use a tree map to maintain sorted order by user ID
    private final Map<Integer, SubscriberUser> userMap =
            new TreeMap<Integer, SubscriberUser>();

    /**
     * Constructs a model cache, retrieving a mapping of SSID to XOS Subscriber
     * IDs from the XOS server.
     */
    CordModelCache() {
        log.info("Initialize model cache");
        ObjectNode map = XosManager.INSTANCE.initXosSubscriberLookups();
        initLookupMap(map);
        log.info("{} entries in SSID->SubID lookup map", LOOKUP.size());
    }

    private void initLookupMap(ObjectNode map) {
        ArrayNode array = (ArrayNode) map.get(KEY_SSID_MAP);
        Iterator<JsonNode> iter = array.elements();
        StringBuilder msg = new StringBuilder();
        while (iter.hasNext()) {
            ObjectNode node = (ObjectNode) iter.next();
            String ssidStr = node.get(KEY_SSID).asText();
            int ssid = Integer.valueOf(ssidStr);
            int subId = node.get(KEY_SUB_ID).asInt();
            LOOKUP.put(ssid, subId);
            msg.append(String.format("\n..binding SSID %s to sub-id %s", ssid, subId));
        }
        log.info(msg.toString());
    }

    private int lookupSubId(int ssid) {
        Integer subId = LOOKUP.get(ssid);
        if (subId == null) {
            log.error("Unmapped SSID: {}", ssid);
            return 0;
        }
        return subId;
    }

    /**
     * Initializes the model for the subscriber account associated with
     * the given email address.
     *
     * @param email the email address
     */
    void init(String email) {
        // defaults to the demo account
        int ssid = DEMO_SSID;

        this.email = email;

        // obviously not scalable, but good enough for demo code...
        if (EMAIL_0.equals(email)) {
            ssid = 0;
        } else if (EMAIL_1.equals(email)) {
            ssid = 1;
        }

        this.ssid = ssid;
        subscriberId = lookupSubId(ssid);
        XosManager.INSTANCE.setXosUtilsForSubscriber(subscriberId);

        // if we are using the demo account, tell XOS to reset it...
        if (ssid == DEMO_SSID) {
            XosManager.INSTANCE.initDemoSubscriber();
        }

        // NOTE: I think the following should work for non-DEMO account...
        currentBundle = new Bundle(BundleFactory.BASIC_BUNDLE);
        initUsers();
    }

    private void initUsers() {
        // start with a clean slate
        userMap.clear();

        ArrayNode users = XosManager.INSTANCE.getUserList();
        if (users == null) {
            log.warn("no user list for SSID {} (subid {})", ssid, subscriberId);
            return;
        }

        StringBuilder sb = new StringBuilder();
        for (JsonNode u: users) {
            ObjectNode user = (ObjectNode) u;

            int id = user.get("id").asInt();
            String name = user.get("name").asText();
            String mac = user.get("mac").asText();
            String level = user.get("level").asText();

            // NOTE: We are just storing the current "url-filter" level.
            //       Since we are starting with the BASIC bundle, (that does
            //       not include URL_FILTER), we don't yet have the URL_FILTER
            //       memento in which to store the level.
            SubscriberUser su = createUser(id, name, mac, level);
            userMap.put(id, su);
            sb.append(String.format("\n..cache user %s [%d], %s, %s",
                                    name, id, mac, level));
        }
        log.info(sb.toString());
    }

    private SubscriberUser createUser(int uid, String name, String mac,
                                      String level) {
        SubscriberUser user = new SubscriberUser(uid, name, mac, level);
        for (XosFunction f: currentBundle.functions()) {
            user.setMemento(f.descriptor(), f.createMemento());
        }
        return user;
    }

    /**
     * Returns the currently selected bundle.
     *
     * @return current bundle
     */
    public Bundle getCurrentBundle() {
        return currentBundle;
    }

    /**
     * Sets a new bundle.
     *
     * @param bundleId bundle identifier
     * @throws IllegalArgumentException if bundle ID is unknown
     */
    public void setCurrentBundle(String bundleId) {
        log.info("set new bundle : {}", bundleId);
        BundleDescriptor bd = BundleFactory.bundleFromId(bundleId);
        currentBundle = new Bundle(bd);
        // update the user mementos
        for (SubscriberUser user: userMap.values()) {
            user.clearMementos();
            for (XosFunction f: currentBundle.functions()) {
                user.setMemento(f.descriptor(), f.createMemento());
                if (f.descriptor().equals(URL_FILTER)) {
                    applyUrlFilterLevel(user, user.urlFilterLevel());
                }
            }
        }

        XosManager.INSTANCE.setNewBundle(currentBundle);
    }


    /**
     * Returns the list of current users for this subscriber account.
     *
     * @return the list of users
     */
    public List<SubscriberUser> getUsers() {
        return ImmutableList.copyOf(userMap.values());
    }

    /**
     * Applies a function parameter change for a user, pushing that
     * change through to XOS.
     *
     * @param userId user identifier
     * @param funcId function identifier
     * @param param function parameter to change
     * @param value new value for function parameter
     */
    public void applyPerUserParam(String userId, String funcId,
                                  String param, String value) {

        int uid = Integer.parseInt(userId);
        SubscriberUser user = userMap.get(uid);
        checkNotNull(user, "unknown user id: " + uid);

        XosFunctionDescriptor xfd =
                XosFunctionDescriptor.valueOf(funcId.toUpperCase());

        XosFunction func = currentBundle.findFunction(xfd);
        checkNotNull(func, "function not part of bundle: " + funcId);
        applyParam(func, user, param, value, true);
    }

    // =============

    private void applyUrlFilterLevel(SubscriberUser user, String level) {
        XosFunction urlFilter = currentBundle.findFunction(URL_FILTER);
        if (urlFilter != null) {
            applyParam(urlFilter, user, LEVEL, level, false);
        }
    }

    private void applyParam(XosFunction func, SubscriberUser user,
                            String param, String value, boolean punchThrough) {
        func.applyParam(user, param, value);
        if (punchThrough) {
            XosManager.INSTANCE.apply(func, user);
        }
    }

    private ArrayNode userJsonArray() {
        ArrayNode userList = arrayNode();
        for (SubscriberUser user: userMap.values()) {
            userList.add(UserFactory.toObjectNode(user));
        }
        return userList;
    }

    // ============= generate JSON for GUI rest calls..

    private void addSubId(ObjectNode root) {
        root.put(SUB_ID, subscriberId);
        root.put(SSID, ssid);
        root.put(EMAIL, email);
    }


    /**
     * Returns response JSON for login request.
     * <p>
     * Depending on which email is used, will bind the GUI to the
     * appropriate XOS Subscriber ID.
     *
     * @param email the supplied email
     * @return JSON acknowledgement
     */
    public synchronized String jsonLogin(String email) {
        log.info("jsonLogin(\"{}\")", email);
        init(email);
        ObjectNode root = objectNode();
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns the dashboard page data as JSON.
     *
     * @return dashboard page JSON data
     */
    public synchronized String jsonDashboard() {
        log.info("jsonDashboard()");

        if (email == null) {
            return jsonLogout();
        }

        ObjectNode root = objectNode();
        root.put(BUNDLE, currentBundle.descriptor().displayName());
        root.set(USERS, userJsonArray());
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns the bundle page data as JSON.
     *
     * @return bundle page JSON data
     */
    public synchronized String jsonBundle() {
        log.info("jsonBundle()");

        if (email == null) {
            return jsonLogout();
        }

        ObjectNode root = BundleFactory.toObjectNode(currentBundle);
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns the users page data as JSON.
     *
     * @return users page JSON data
     */
    public synchronized String jsonUsers() {
        log.info("jsonUsers()");

        if (email == null) {
            return jsonLogout();
        }

        ObjectNode root = objectNode();
        root.set(USERS, userJsonArray());
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns logout acknowledgement as JSON.
     *
     * @return logout acknowledgement
     */
    public synchronized String jsonLogout() {
        log.info("jsonLogout()");
        ObjectNode root = objectNode().put(LOGOUT, true);
        addSubId(root);

        email = null;   // signifies no one logged in

        return root.toString();
    }

    /**
     * Singleton instance.
     */
    public static final CordModelCache INSTANCE = new CordModelCache();
}
