/*
 * 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";
    // FIXME: should not be a colon in the key..... Scott to fix on XOS
    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 Map<Integer, Integer> LOOKUP = new HashMap<>();

    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();
        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);
            log.info("... binding SSID {} to sub-id {}", ssid, subId);
        }
    }

    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;

        // 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() {
        ArrayNode users = XosManager.INSTANCE.getUserList();
        if (users == null) {
            log.warn("no user list for SSID {} (subid {})", ssid, subscriberId);
            return;
        }

        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);
            log.info("..caching user {} (id:{})", name, id);
        }
    }

    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);
    }


    /**
     * 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 String jsonLogin(String email) {
        init(email);
        ObjectNode root = objectNode();
        root.put(EMAIL, email);
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns the dashboard page data as JSON.
     *
     * @return dashboard page JSON data
     */
    public String jsonDashboard() {
        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 String jsonBundle() {
        ObjectNode root = BundleFactory.toObjectNode(currentBundle);
        addSubId(root);
        return root.toString();
    }

    /**
     * Returns the users page data as JSON.
     *
     * @return users page JSON data
     */
    public String jsonUsers() {
        ObjectNode root = objectNode();
        root.set(USERS, userJsonArray());
        addSubId(root);
        return root.toString();
    }

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