/*
 * Copyright 2016-present 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.yms.app.ysr;

import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangModule;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangSubModule;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yms.ysr.YangModuleIdentifier;
import org.onosproject.yms.ysr.YangModuleInformation;
import org.onosproject.yms.ysr.YangModuleLibrary;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;

import static java.util.Collections.sort;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.parseJarFile;
import static org.onosproject.yangutils.utils.UtilConstants.EVENT_STRING;
import static org.onosproject.yangutils.utils.UtilConstants.HYPHEN;
import static org.onosproject.yangutils.utils.UtilConstants.OP_PARAM;
import static org.onosproject.yangutils.utils.UtilConstants.PERIOD;
import static org.onosproject.yangutils.utils.UtilConstants.SERVICE;
import static org.onosproject.yangutils.utils.UtilConstants.SLASH;
import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
import static org.osgi.framework.FrameworkUtil.getBundle;
import static org.slf4j.LoggerFactory.getLogger;


/**
 * Representation of default YANG schema registry. Yang schema registry
 * provides interface to an application to register its YANG schema
 * with YMS. It provides YANG schema nodes to YDT, YNB and YSB.
 */
public class DefaultYangSchemaRegistry implements YangSchemaRegistry {

    private static final String SYSTEM = SLASH + "system" + SLASH;
    private static final String MAVEN = "mvn:";
    private static final String JAR = ".jar";
    private static final String USER_DIRECTORY = "user.dir";
    private static final String AT = "@";
    private static final String DATE_FORMAT = "yyyy-mm-dd";
    private static final String ONOS = "org.onosproject";
    private static final Logger log = getLogger(DefaultYangSchemaRegistry.class);

    /*
     * Map for storing app objects.
     */
    private final ConcurrentMap<String, Object> appObjectStore;

    /*
     * Map for storing YANG schema nodes.
     */
    private final ConcurrentMap<String, ConcurrentMap<String, YangSchemaNode>>
            yangSchemaStore;

    /*
     * Map for storing YANG schema nodes with respect to root's generated
     * interface file name.
     */
    private final ConcurrentMap<String, YangSchemaNode> interfaceNameKeyStore;

    /*
     * Map for storing YANG schema nodes root's generated op param file name.
     */
    private final ConcurrentMap<String, YangSchemaNode> opParamNameKeyStore;

    /*
     * Map for storing YANG schema nodes with respect to notifications.
     */
    private final ConcurrentMap<String, YangSchemaNode> eventNameKeyStore;

    /*
     * Map for storing YANG schema nodes with respect to app name.
     */
    private final ConcurrentMap<String, YangSchemaNode> appNameKeyStore;

    /*
     * Map for storing registered classes.
     */
    private final ConcurrentMap<String, Class<?>> registerClassStore;

    /*
     * Map for storing YANG file details.
     */
    private final ConcurrentMap<YangModuleIdentifier, String> yangFileStore;

    private final ConcurrentMap<Object, Boolean> ynhRegistrationStore;
    private final ConcurrentMap<String, String> jarPathStore;

    /**
     * Creates an instance of default YANG schema registry.
     */
    public DefaultYangSchemaRegistry() {
        appObjectStore = new ConcurrentHashMap<>();
        yangSchemaStore = new ConcurrentHashMap<>();
        interfaceNameKeyStore = new ConcurrentHashMap<>();
        opParamNameKeyStore = new ConcurrentHashMap<>();
        eventNameKeyStore = new ConcurrentHashMap<>();
        registerClassStore = new ConcurrentHashMap<>();
        yangFileStore = new ConcurrentHashMap<>();
        appNameKeyStore = new ConcurrentHashMap<>();
        ynhRegistrationStore = new ConcurrentHashMap<>();
        jarPathStore = new ConcurrentHashMap<>();
    }


    @Override
    public void registerApplication(Object appObject, Class<?> serviceClass) {
        synchronized (serviceClass) {
            doPreProcessing(serviceClass, appObject);
            if (!verifyIfApplicationAlreadyRegistered(serviceClass)) {
                BundleContext context = getBundle(serviceClass).getBundleContext();
                Bundle[] bundles = context.getBundles();
                Bundle bundle;
                int len = bundles.length;
                List<YangNode> curNodes;
                String jarPath;
                for (int i = len - 1; i >= 0; i--) {
                    bundle = bundles[i];
                    if (bundle.getSymbolicName().contains(ONOS)) {
                        jarPath = getJarPathFromBundleLocation(
                                bundle.getLocation(), context.getProperty(USER_DIRECTORY));
                        curNodes = processJarParsingOperations(jarPath);
                        // process application registration.
                        if (curNodes != null && !curNodes.isEmpty()) {
                            jarPathStore.put(serviceClass.getName(), jarPath);
                            processRegistration(serviceClass, jarPath,
                                                curNodes, appObject, false);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void unRegisterApplication(Object managerObject,
                                      Class<?> serviceClass) {
        synchronized (serviceClass) {
            YangSchemaNode curNode;
            String serviceName = serviceClass.getName();

            //Check if service should be unregistered?
            if (managerObject != null) {
                verifyApplicationRegistration(managerObject, serviceClass);
            }
            //Remove registered class from store.
            registerClassStore.remove(serviceName);
            //check if service is in app store.
            curNode = appNameKeyStore.get(serviceName);
            if (curNode == null) {
                curNode = interfaceNameKeyStore.get(serviceName);
            }

            if (curNode != null) {
                removeSchemaNode(curNode);
                eventNameKeyStore.remove(getEventClassName(curNode));
                appObjectStore.remove(serviceName);
                interfaceNameKeyStore.remove(getInterfaceClassName(curNode));
                opParamNameKeyStore.remove(getOpParamClassName(curNode));
                yangFileStore.remove(getModuleIdentifier(curNode));
                appNameKeyStore.remove(serviceName);
                removeYsrGeneratedTemporaryResources(jarPathStore.get(serviceName),
                                                     serviceName);
                log.info(" service {} is unregistered.",
                         serviceClass.getSimpleName());
            } else {
                throw new RuntimeException(serviceClass.getSimpleName() +
                                                   " service was not registered.");
            }
        }
    }

    @Override
    public Object getRegisteredApplication(YangSchemaNode schemaNode) {
        Object obj = null;
        if (schemaNode != null) {
            String name = getServiceName(schemaNode);
            obj = appObjectStore.get(name);
            if (obj == null) {
                log.error("{} not found.", name);
            }
        }
        return obj;
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingSchemaName(String schemaName) {
        return getSchemaNodeUsingSchemaNameWithRev(schemaName);
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingAppName(String appName) {
        YangSchemaNode node = appNameKeyStore.get(appName);
        if (node == null) {
            log.error("{} not found.", appName);
        }
        return node;
    }

    @Override
    public YangSchemaNode
    getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(String name) {
        YangSchemaNode node = interfaceNameKeyStore.get(name);
        if (node == null) {
            log.error("{} not found.", name);
        }
        return node;
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName(
            String name) {
        YangSchemaNode node = opParamNameKeyStore.get(name);
        if (node == null) {
            log.error("{} not found.", name);
        }
        return node;
    }

    @Override
    public YangSchemaNode getRootYangSchemaNodeForNotification(String name) {
        YangSchemaNode node = eventNameKeyStore.get(name);
        if (node == null) {
            log.error("{} not found.", name);
        }
        return node;
    }

    @Override
    public Class<?> getRegisteredClass(YangSchemaNode schemaNode) {
        String interfaceName = getInterfaceClassName(schemaNode);
        String serviceName = getServiceName(schemaNode);
        Class<?> regClass = registerClassStore.get(serviceName);
        if (regClass == null) {
            regClass = registerClassStore.get(interfaceName);
        }
        return regClass;
    }

    @Override
    public String getYangFile(YangModuleIdentifier moduleIdentifier) {
        String file = yangFileStore.get(moduleIdentifier);
        if (file == null) {
            log.error("YANG files for corresponding module identifier {} not " +
                              "found", moduleIdentifier);
        }
        return file;
    }

    @Override
    public boolean verifyNotificationObject(Object appObj, Class<?> service) {
        synchronized (service) {
            YangSchemaNode node = appNameKeyStore.get(service.getName());
            if (node == null) {
                log.error("application is not registered with YMS {}",
                          service.getName());
                return false;
            }
            try {
                if (node.isNotificationPresent()) {
                    if (appObj != null) {
                        Boolean ifPresent = ynhRegistrationStore.get(appObj);
                        if (ifPresent == null) {
                            ynhRegistrationStore.put(appObj, true);
                            return true;
                        }
                    }
                }
            } catch (DataModelException e) {
                log.error("notification registration error: {} {}", e
                        .getLocalizedMessage(), e);
            }
            return false;
        }
    }

    @Override
    public void flushYsrData() {
        appObjectStore.clear();
        yangSchemaStore.clear();
        eventNameKeyStore.clear();
        opParamNameKeyStore.clear();
        interfaceNameKeyStore.clear();
        registerClassStore.clear();
        yangFileStore.clear();
    }

    @Override
    public void processModuleLibrary(String serviceName,
                                     YangModuleLibrary library) {
        synchronized (serviceName) {
            YangSchemaNode node = appNameKeyStore.get(serviceName);
            if (node != null) {
                YangModuleInformation moduleInformation =
                        new DefaultYangModuleInformation(getModuleIdentifier(node),
                                                         node.getNameSpace());
                addSubModuleIdentifier(node, (
                        DefaultYangModuleInformation) moduleInformation);
                //TODO: add feature list to module information.
                ((DefaultYangModuleLibrary) library)
                        .addModuleInformation(moduleInformation);
            }
        }
    }

    /**
     * Process service class.
     *
     * @param serviceClass service class
     * @param appObject    application object
     */

    void doPreProcessing(Class<?> serviceClass, Object appObject) {

        //Check if service should be registered?
        if (appObject != null) {
            verifyApplicationRegistration(appObject, serviceClass);
        }
        String name = serviceClass.getName();
        //Add app class to registered service store.
        if (!registerClassStore.containsKey(name)) {
            registerClassStore.put(name, serviceClass);
        }
    }

    void updateServiceClass(Class<?> service) {
        registerClassStore.put(service.getName(), service);
    }

    /**
     * Process application registration.
     *
     * @param service  service class
     * @param jarPath  jar path
     * @param nodes    YANG nodes
     * @param appObj   application object
     * @param isFromUt if registration is being called form unit test
     */
    void processRegistration(Class<?> service, String jarPath,
                             List<YangNode> nodes,
                             Object appObj, boolean isFromUt) {

        // process storing operations.
        YangNode schemaNode = findNodeWhichShouldBeReg(service.getName(), nodes);
        if (schemaNode != null) {
            if (appObj != null) {
                appObjectStore.put(service.getName(), appObj);
            }
            //Process application context for registrations.
            processApplicationContext(schemaNode, service.getName(), isFromUt);
            //Update YANG file store.
            updateYangFileStore(schemaNode, jarPath);
        }
    }

    /**
     * Returns the node for which corresponding class is generated.
     *
     * @param name  generated class name
     * @param nodes list of yang nodes
     * @return node for which corresponding class is generated
     */
    private YangNode findNodeWhichShouldBeReg(String name, List<YangNode> nodes) {
        for (YangNode node : nodes) {
            if (name.equals(getServiceName(node)) ||
                    name.equals(getInterfaceClassName(node))) {
                return node;
            }
        }
        return null;
    }

    /**
     * Verifies if service class should be registered or not.
     *
     * @param appObject application object
     * @param appClass  application class
     */
    private void verifyApplicationRegistration(Object appObject,
                                               Class<?> appClass) {
        Class<?> managerClass = appObject.getClass();
        Class<?>[] services = managerClass.getInterfaces();
        List<Class<?>> classes = new ArrayList<>();
        Collections.addAll(classes, services);
        if (!classes.contains(appClass)) {
            throw new RuntimeException("service class " + appClass.getName() +
                                               "is not being implemented by " +
                                               managerClass.getName());
        }
    }

    /**
     * Verifies if application is already registered with YMS.
     *
     * @param appClass application class
     * @return true if application already registered
     */
    private boolean verifyIfApplicationAlreadyRegistered(Class<?> appClass) {
        String appName = appClass.getName();
        return appObjectStore.containsKey(appName) ||
                interfaceNameKeyStore.containsKey(appName);
    }

    /**
     * Updates yang file store for YANG node.
     *
     * @param node    YANG node
     * @param jarPath jar file path
     */
    private void updateYangFileStore(YangNode node, String jarPath) {
        yangFileStore.put(getModuleIdentifier(node),
                          getYangFilePath(jarPath, node.getFileName()));
    }

    /**
     * Returns yang file path.
     *
     * @param jarPath          jar path
     * @param metaDataFileName name of yang file from metadata
     * @return yang file path
     */
    private String getYangFilePath(String jarPath, String metaDataFileName) {
        String[] metaData = metaDataFileName.split(SLASH);
        return jarPath + SLASH + metaData[metaData.length - 1];
    }

    /**
     * Process jar file for fetching YANG nodes.
     *
     * @param path jar file path
     * @return YANG schema nodes
     */
    private List<YangNode> processJarParsingOperations(String path) {
        //Deserialize data model and get the YANG node set.
        String jar = path + JAR;
        try {
            File file = new File(jar);
            if (file.exists()) {
                return parseJarFile(path + JAR, path);
            }
        } catch (IOException e) {
            log.error(" failed to parse the jar file in path {} : {} ", path,
                      e.getMessage());
        }
        return null;
    }

    /**
     * Process an application an updates the maps for YANG schema registry.
     *
     * @param appNode  application YANG schema nodes
     * @param name     class name
     * @param isFormUt if method is being called from unit tests
     */
    private void processApplicationContext(YangSchemaNode appNode, String name,
                                           boolean isFormUt) {

        //Update map for which registrations is being called.
        appNameKeyStore.put(name, appNode);

        // Updates schema store.
        addToSchemaStore(appNode);
        // update interface store.
        interfaceNameKeyStore.put(getInterfaceClassName(appNode), appNode);

        //update op param store.
        opParamNameKeyStore.put(getOpParamClassName(appNode), appNode);
        //Checks if notification is present then update notification store map.
        String eventSubject = null;
        try {
            if (appNode.isNotificationPresent()) {
                eventSubject = getEventClassName(appNode);
            }
        } catch (DataModelException e) {
            log.error("failed to search notification from schema map : {}",
                      e.getLocalizedMessage());
        }
        if (eventSubject != null) {
            eventNameKeyStore.put(eventSubject, appNode);
        }
        if (!isFormUt) {
            log.info("successfully registered this application {}", name);
        }
    }

    /**
     * Returns jar path from bundle mvnLocationPath.
     *
     * @param mvnLocationPath mvnLocationPath of bundle
     * @return path of jar
     */
    private String getJarPathFromBundleLocation(String mvnLocationPath,
                                                String currentDirectory) {
        String path = currentDirectory + SYSTEM;
        if (mvnLocationPath.contains(MAVEN)) {
            String[] strArray = mvnLocationPath.split(MAVEN);
            if (strArray[1].contains(File.separator)) {
                String[] split = strArray[1].split(File.separator);
                if (split[0].contains(PERIOD)) {
                    String[] groupId = split[0].split(Pattern.quote(PERIOD));
                    return path + groupId[0] + SLASH + groupId[1] + SLASH + split[1] +
                            SLASH + split[2] + SLASH + split[1] + HYPHEN + split[2];
                }
            }
        }
        return null;
    }

    /**
     * Returns schema node based on the revision.
     *
     * @param name name of the schema node
     * @return schema node based on the revision
     */
    private YangSchemaNode getSchemaNodeUsingSchemaNameWithRev(String name) {
        ConcurrentMap<String, YangSchemaNode> revMap;
        YangSchemaNode schemaNode;
        if (name.contains(AT)) {
            String[] revArray = name.split(AT);
            revMap = yangSchemaStore.get(revArray[0]);
            schemaNode = revMap.get(name);
            if (schemaNode == null) {
                log.error("{} not found.", name);
            }
            return schemaNode;
        }
        if (yangSchemaStore.containsKey(name)) {
            revMap = yangSchemaStore.get(name);
            if (revMap != null && !revMap.isEmpty()) {
                YangSchemaNode node = revMap.get(name);
                if (node != null) {
                    return node;
                }
                String revName = getLatestVersion(revMap);
                return revMap.get(revName);
            }
        }
        log.error("{} not found.", name);
        return null;
    }

    private String getLatestVersion(ConcurrentMap<String, YangSchemaNode> revMap) {
        List<String> keys = new ArrayList<>();
        for (Map.Entry<String, YangSchemaNode> entry : revMap.entrySet()) {
            keys.add(entry.getKey());
        }
        sort(keys);
        return keys.get(keys.size() - 1);
    }

    /**
     * Adds schema node when different revision of node has received.
     *
     * @param schemaNode schema node
     */
    private void addToSchemaStore(YangSchemaNode schemaNode) {

        String date = getDateInStringFormat(schemaNode);
        String name = schemaNode.getName();
        String revName = name;
        if (date != null) {
            revName = name + AT + date;
        }
        //check if already present.
        if (!yangSchemaStore.containsKey(name)) {
            ConcurrentMap<String, YangSchemaNode> revStore =
                    new ConcurrentHashMap<>();
            revStore.put(revName, schemaNode);
            yangSchemaStore.put(name, revStore);
        } else {
            yangSchemaStore.get(name).put(revName, schemaNode);
        }
    }

    /**
     * Returns date in string format.
     *
     * @param schemaNode schema node
     * @return date in string format
     */
    String getDateInStringFormat(YangSchemaNode schemaNode) {
        if (schemaNode != null) {
            if (((YangNode) schemaNode).getRevision() != null) {
                return new SimpleDateFormat(DATE_FORMAT)
                        .format(((YangNode) schemaNode).getRevision()
                                        .getRevDate());
            }
        }
        return null;
    }

    /**
     * Removes schema node from schema map.
     *
     * @param removableNode schema node which needs to be removed
     */
    private void removeSchemaNode(YangSchemaNode removableNode) {
        String name = removableNode.getName();
        String revName = name;
        String date = getDateInStringFormat(removableNode);
        if (date != null) {
            revName = name + AT + date;
        }
        ConcurrentMap<String, YangSchemaNode> revMap = yangSchemaStore.get(name);
        if (revMap != null && !revMap.isEmpty() && revMap.size() != 1) {
            revMap.remove(revName);
        } else {
            yangSchemaStore.remove(removableNode.getName());
        }
    }

    /**
     * Adds sub module identifier.
     *
     * @param node        schema node
     * @param information module information
     */
    private void addSubModuleIdentifier(
            YangSchemaNode node, DefaultYangModuleInformation information) {
        List<YangInclude> includeList = new ArrayList<>();
        if (node instanceof YangModule) {
            includeList = ((YangModule) node).getIncludeList();
        } else if (node instanceof YangSubModule) {
            includeList = ((YangSubModule) node).getIncludeList();
        }
        for (YangInclude include : includeList) {
            information.addSubModuleIdentifiers(getModuleIdentifier(
                    include.getIncludedNode()));
        }
    }

    /**
     * Returns module identifier for schema node.
     *
     * @param schemaNode schema node
     * @return module identifier for schema node
     */
    private YangModuleIdentifier getModuleIdentifier(
            YangSchemaNode schemaNode) {
        return new DefaultYangModuleIdentifier(
                schemaNode.getName(), getDateInStringFormat(schemaNode));
    }

    /**
     * Returns schema node's generated interface class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated interface class name
     */
    String getInterfaceClassName(YangSchemaNode schemaNode) {
        return schemaNode.getJavaPackage() + PERIOD +
                getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType());
    }

    /**
     * Returns schema node's generated op param class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated op param class name
     */
    private String getOpParamClassName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode) + OP_PARAM;
    }

    /**
     * Returns schema node's generated event class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated event class name
     */
    private String getEventClassName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode).toLowerCase() + PERIOD +
                getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType()) +
                EVENT_STRING;
    }

    /**
     * Returns schema node's generated service class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated service class name
     */
    String getServiceName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode) + SERVICE;
    }

    /**
     * Removes YSR generated temporary resources.
     *
     * @param rscPath resource path
     * @param appName application name
     */
    private void removeYsrGeneratedTemporaryResources(String rscPath,
                                                      String appName) {
        if (rscPath != null) {
            File jarPath = new File(rscPath);
            if (jarPath.exists()) {
                try {
                    deleteDirectory(jarPath);
                } catch (IOException e) {
                    log.error("failed to delete ysr resources for {} : {}",
                              appName, e.getLocalizedMessage());
                }
            }
        }
    }
}