/*
 *  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.ui.impl.topo;

import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicUiTopoLayoutConfig;
import org.onosproject.net.region.RegionId;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.model.topo.UiTopoLayoutId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.ui.model.topo.UiTopoLayoutId.DEFAULT_ID;

/**
 * Manages the user interface topology layouts.
 * Note that these layouts are persisted and distributed across the cluster.
 */
@Component(immediate = true)
@Service
public class UiTopoLayoutManager implements UiTopoLayoutService {

    private static final String ID_NULL = "Layout ID cannot be null";
    private static final String LAYOUT_NULL = "Layout cannot be null";

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

    private final InternalConfigListener cfgListener = new InternalConfigListener();
    private final Map<UiTopoLayoutId, UiTopoLayout> layoutMap = new HashMap<>();

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry cfgService;


    @Activate
    public void activate() {

        // Create and add the default layout, if needed.
        layoutMap.computeIfAbsent(DEFAULT_ID, UiTopoLayout::new);

        cfgService.addListener(cfgListener);
        cfgListener.initAllConfigs();

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        cfgService.removeListener(cfgListener);

        log.info("Stopped");
    }


    @Override
    public UiTopoLayout getRootLayout() {
        return getLayout(DEFAULT_ID);
    }

    @Override
    public Set<UiTopoLayout> getLayouts() {
        return ImmutableSet.copyOf(layoutMap.values());
    }

    @Override
    public boolean addLayout(UiTopoLayout layout) {
        checkNotNull(layout, LAYOUT_NULL);
        return layoutMap.put(layout.id(), layout) == null;
    }

    @Override
    public UiTopoLayout getLayout(UiTopoLayoutId layoutId) {
        checkNotNull(layoutId, ID_NULL);
        return layoutMap.get(layoutId);
    }

    @Override
    public UiTopoLayout getLayout(RegionId regionId) {
        if (regionId == null || regionId.equals(UiRegion.NULL_ID)) {
            return getRootLayout();
        }

        List<UiTopoLayout> matchingLayouts = layoutMap.values().stream()
                .filter(l -> Objects.equals(regionId, l.regionId()))
                .collect(Collectors.toList());
        return matchingLayouts.isEmpty() ? null : matchingLayouts.get(0);
    }

    @Override
    public Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId) {
        checkNotNull(layoutId, ID_NULL);

        UiTopoLayout layout = layoutMap.get(layoutId);
        if (layout == null || layout.isRoot()) {
            return Collections.emptySet();
        }

        UiTopoLayoutId parentId = layout.parent();
        return layoutMap.values().stream()
                // all layouts who are NOT me (or root) and who share my parent...
                .filter(l -> !Objects.equals(l.id(), layoutId) &&
                        !Objects.equals(l.id(), UiTopoLayoutId.DEFAULT_ID) &&
                        Objects.equals(l.parent(), parentId))
                .collect(Collectors.toSet());
    }

    @Override
    public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
        checkNotNull(layoutId, ID_NULL);
        return layoutMap.values().stream()
                .filter(l -> !l.isRoot() && Objects.equals(l.parent(), layoutId))
                .collect(Collectors.toSet());
    }

    @Override
    public boolean removeLayout(UiTopoLayout layout) {
        checkNotNull(layout, LAYOUT_NULL);
        return layoutMap.remove(layout.id()) != null;
    }

    /*
     * Listens for changes to layout configs, updating instances as necessary
     */
    private class InternalConfigListener implements NetworkConfigListener {

        // look up the current config by layout ID and apply it
        private void updateLayoutConfig(UiTopoLayoutId id) {
            BasicUiTopoLayoutConfig cfg =
                    cfgService.getConfig(id, BasicUiTopoLayoutConfig.class);

            log.info("Updating Layout via config... {}: {}", id, cfg);

            UiTopoLayout layout = layoutMap.get(id);

            // NOTE: if a value is null, then that null-ness should be set
            // TODO: add setters on UiTopoLayout and implement...
//            layout
//              .region(cfg.region())
//              .parent(cfg.parent())
//              .geomap(cfg.geomap())
//              .sprites(cfg.sprites())
//              .scale(cfg.scale())
//              .offsetX(cfg.offsetX())
//              .offsetY(cfg.offsetY());
        }

        private void initAllConfigs() {
            log.info("Initializing layout configurations...");
            layoutMap.keySet().forEach(this::updateLayoutConfig);
        }

        @Override
        public void event(NetworkConfigEvent event) {
            UiTopoLayoutId id = (UiTopoLayoutId) event.subject();
            updateLayoutConfig(id);
        }

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
                    event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
                    event.configClass().equals(BasicUiTopoLayoutConfig.class);
        }
    }
}
