/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.xran.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import io.netty.channel.ChannelHandlerContext;
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.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.store.AbstractStore;
import org.onosproject.xran.XranService;
import org.onosproject.xran.XranStore;
import org.onosproject.xran.asn1lib.api.CRNTI;
import org.onosproject.xran.asn1lib.api.ECGI;
import org.onosproject.xran.asn1lib.api.EUTRANCellIdentifier;
import org.onosproject.xran.asn1lib.api.PCIARFCN;
import org.onosproject.xran.impl.entities.RnibCell;
import org.onosproject.xran.impl.entities.RnibLink;
import org.onosproject.xran.impl.entities.RnibSlice;
import org.onosproject.xran.impl.entities.RnibUe;
import org.onosproject.xran.impl.identifiers.EcgiCrntiPair;
import org.onosproject.xran.impl.identifiers.LinkId;
import org.slf4j.Logger;

import javax.xml.bind.DatatypeConverter;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Default xran store.
 */
@Component(immediate = true)
@Service
public class DefaultXranStore extends AbstractStore implements XranStore {
    private static final String XRAN_APP_ID = "org.onosproject.xran";

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    protected ConcurrentMap<LinkId, RnibLink> linkMap = new ConcurrentHashMap<>();
    private ConcurrentMap<ECGI, RnibCell> cellMap = new ConcurrentHashMap<>();
    private ConcurrentMap<Long, RnibUe> ueMap = new ConcurrentHashMap<>();
    private ConcurrentMap<Object, RnibSlice> sliceMap = new ConcurrentHashMap<>();

    private XranService controller;
    private IdGenerator ueIdGenerator;

    // map to get the context channel based on ecgi
    private ConcurrentMap<ECGI, ChannelHandlerContext> ctxMap = new ConcurrentHashMap<>();
    // pci-arfcn to ecgi bimap
    private BiMap<PCIARFCN, ECGI> pciarfcnMap = HashBiMap.create();
    // ECGI, CRNTI pair of primary cell for specified UE.
    private BiMap<EcgiCrntiPair, Long> crntiMap = HashBiMap.create();


    @Activate
    public void activate() {
        ApplicationId appId = coreService.getAppId(XRAN_APP_ID);

        // create ue id generator
        ueIdGenerator = coreService.getIdGenerator("xran-ue-id");

        log.info("XRAN Default Store Started");
    }

    @Deactivate
    public void deactivate() {
        linkMap.clear();
        cellMap.clear();
        ueMap.clear();
        sliceMap.clear();

        controller = null;
        ueIdGenerator = null;

        log.info("XRAN Default Store Stopped");
    }

    @Override
    public List<RnibLink> getLinks() {
        List<RnibLink> list = Lists.newArrayList();
        list.addAll(linkMap.values());
        return list;
    }

    @Override
    public List<RnibLink> getLinks(ECGI ecgi) {
        List<RnibLink> list = Lists.newArrayList();
        list.addAll(
                linkMap.keySet()
                        .stream()
                        .filter(k -> k.getEcgi().equals(ecgi))
                        .map(v -> linkMap.get(v))
                        .collect(Collectors.toList()));
        return list;
    }

    @Override
    public List<RnibLink> getLinks(String eciHex) {
        List<RnibLink> list = Lists.newArrayList();
        EUTRANCellIdentifier eci = hexToEci(eciHex);

        list.addAll(
                linkMap.keySet()
                        .stream()
                        .filter(k -> k.getEcgi().getEUTRANcellIdentifier().equals(eci))
                        .map(v -> linkMap.get(v))
                        .collect(Collectors.toList()));

        return list;
    }

    @Override
    public List<RnibLink> getLinks(long euId) {
        List<RnibLink> list = Lists.newArrayList();

        list.addAll(
                linkMap.keySet()
                        .stream()
                        .filter(k -> k.getUeId().equals(euId))
                        .map(v -> linkMap.get(v))
                        .collect(Collectors.toList()));

        return list;
    }


    @Override
    public Optional<RnibLink> getLink(String eciHex, long euId) {
        EUTRANCellIdentifier eci = hexToEci(eciHex);

        Optional<LinkId> first = linkMap.keySet()
                .stream()
                .filter(linkId -> linkId.getEcgi().getEUTRANcellIdentifier().equals(eci) &&
                        linkId.getUeId().equals(euId))
                .findFirst();

        return first.map(linkId -> linkMap.get(linkId));
    }

    @Override
    public void storeLink(RnibLink link) {
        synchronized (this) {
            if (link.getLinkId() != null) {
                // if we add a primary link then change the primary to non serving
                if (link.getType().equals(RnibLink.Type.SERVING_PRIMARY)) {
                    RnibUe ue = link.getLinkId().getUe();
                    getLinks(ue.getId())
                            .stream()
                            .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
                            .forEach(l -> l.setType(RnibLink.Type.NON_SERVING));
                }
                linkMap.put(link.getLinkId(), link);
            }
        }
    }

    @Override
    public boolean removeLink(LinkId link) {
        return linkMap.remove(link) != null;
    }

    @Override
    public Optional<RnibLink> getLink(ECGI ecgi, Long ueId) {
        LinkId linkId = LinkId.valueOf(ecgi, ueId);
        return Optional.ofNullable(linkMap.get(linkId));
    }

    @Override
    public Optional<RnibLink> getLink(ECGI src, CRNTI dst) {
        return getUe(src, dst).flatMap(ue -> getLink(src, ue.getId()));
    }

    @Override
    public void modifyLinkRrmConf(RnibLink link, JsonNode rrmConf) {
        link.modifyRrmParameters(rrmConf);
    }

    @Override
    public List<Object> getNodes() {
        List<Object> list = Lists.newArrayList();
        list.addAll(cellMap.values());
        list.addAll(ueMap.values());
        return list;
    }

    @Override
    public List<RnibCell> getCellNodes() {
        List<RnibCell> list = Lists.newArrayList();
        list.addAll(cellMap.values());
        return list;
    }

    @Override
    public List<RnibUe> getUeNodes() {
        List<RnibUe> list = Lists.newArrayList();
        list.addAll(ueMap.values());
        return list;
    }

    @Override
    public Optional<Object> getNode(String nodeId) {
        try {
            return Optional.ofNullable(getCell(nodeId));
        } catch (Exception ignored) {
        }
        return Optional.ofNullable(getUe(Long.parseLong(nodeId)));
    }

    @Override
    public void storeCell(RnibCell cell) {
        if (cell.getEcgi() != null) {
            cellMap.putIfAbsent(cell.getEcgi(), cell);
        }
    }

    @Override
    public boolean removeCell(ECGI ecgi) {
        pciarfcnMap.inverse().remove(ecgi);
        ctxMap.remove(ecgi);
        return cellMap.remove(ecgi) != null;
    }

    @Override
    public boolean removeCell(PCIARFCN pciarfcn) {
        return removeCell(pciarfcnMap.get(pciarfcn));
    }

    @Override
    public Optional<RnibCell> getCell(String hexeci) {
        EUTRANCellIdentifier eci = hexToEci(hexeci);
        Optional<ECGI> first = cellMap.keySet()
                .stream()
                .filter(ecgi -> ecgi.getEUTRANcellIdentifier().equals(eci))
                .findFirst();
        return first.map(ecgi -> cellMap.get(ecgi));
    }

    @Override
    public Optional<RnibCell> getCell(ECGI ecgi) {
        return Optional.ofNullable(cellMap.get(ecgi));
    }

    @Override
    public Optional<RnibCell> getCell(PCIARFCN id) {
        ECGI ecgi;
        ecgi = pciarfcnMap.get(id);
        return getCell(ecgi);
    }

    @Override
    public void modifyCellRrmConf(RnibCell cell, JsonNode rrmConf) throws Exception {
        List<RnibLink> linkList = getLinks(cell.getEcgi());
        List<RnibUe> ueList = linkList.stream()
                .map(link -> link.getLinkId().getUe())
                .collect(Collectors.toList());

        cell.modifyRrmConfig(rrmConf, ueList);
    }

    @Override
    public Optional<RnibSlice> getSlice(long sliceId) {
        return Optional.ofNullable(sliceMap.get(sliceId));
    }

    @Override
    public boolean createSlice(ObjectNode attributes) {
        return false;
    }

    @Override
    public boolean removeCell(long sliceId) {
        return sliceMap.remove(sliceId) != null;
    }

    @Override
    public Optional<XranService> getController() {
        return Optional.ofNullable(controller);
    }

    @Override
    public void setController(XranService controller) {
        this.controller = controller;
    }

    @Override
    public void storeUe(RnibUe ue) {
        long newId;
        if (ue.getId() == null) {
            newId = ueIdGenerator.getNewId();
            ue.setId(newId);
        } else {
            newId = ue.getId();
        }
        ueMap.put(newId, ue);
    }

    @Override
    public void storeUe(RnibCell cell, RnibUe ue) {
        storeUe(ue);
        storeCrnti(cell, ue);
    }

    @Override
    public boolean removeUe(long ueId) {
        log.info("removing ue {} {}", ueId, ueMap);
        crntiMap.inverse().remove(ueId);
        return ueMap.remove(ueId) != null;
    }

    @Override
    public void storePciArfcn(RnibCell value) {
        value.getOptConf().ifPresent(cfg -> {
            PCIARFCN pciarfcn = new PCIARFCN();
            pciarfcn.setPci(cfg.getPci());
            pciarfcn.setEarfcnDl(cfg.getEarfcnDl());
            pciarfcnMap.put(pciarfcn, value.getEcgi());
        });
    }

    @Override
    public void storeCtx(RnibCell value, ChannelHandlerContext ctx) {
        if (value.getEcgi() != null) {
            ctxMap.put(value.getEcgi(), ctx);
            storeCell(value);
        }
    }

    @Override
    public Optional<ChannelHandlerContext> getCtx(ECGI ecgi) {
        return Optional.ofNullable(ctxMap.get(ecgi));
    }

    @Override
    public BiMap<EcgiCrntiPair, Long> getCrnti() {
        return crntiMap;
    }

    @Override
    public void storeCrnti(RnibCell cell, RnibUe ue) {
        CRNTI crnti = ue.getCrnti();
        ECGI ecgi = cell.getEcgi();

        if (crnti != null && ecgi != null) {
            // check if there is an ecgi, crnti pair for this UE id.
            EcgiCrntiPair oldPair = crntiMap.inverse().get(ue.getId()),
                    newPair = EcgiCrntiPair.valueOf(cell.getEcgi(), ue.getCrnti());

            if (oldPair == null) {
                crntiMap.put(newPair, ue.getId());
            } else {
                // remove old pair and add the new pair which corresponds to the primary cell.
                crntiMap.inverse().remove(ue.getId());
                crntiMap.put(newPair, ue.getId());
            }
        }
    }

    @Override
    public void putPrimaryLink(RnibCell cell, RnibUe ue) {
        RnibLink link = new RnibLink(cell, ue);
        // set link to primary before storing
        link.setType(RnibLink.Type.SERVING_PRIMARY);
        storeLink(link);
        storeCrnti(cell, ue);
    }

    @Override
    public Optional<RnibLink> putNonServingLink(RnibCell cell, CRNTI crnti) {
        return getUe(cell.getEcgi(), crnti).map(ue -> {
            RnibLink link = new RnibLink(cell, ue);
            storeLink(link);
            return Optional.of(link);
        }).orElse(Optional.empty());
    }

    @Override
    public Optional<RnibLink> putNonServingLink(RnibCell cell, Long ueId) {
        return getUe(ueId).map(ue -> {
            RnibLink link = new RnibLink(cell, ue);
            storeLink(link);
            return Optional.of(link);
        }).orElse(Optional.empty());
    }

    @Override
    public Optional<CRNTI> getCrnti(Long ueId) {
        return Optional.ofNullable(getCrnti().inverse().get(ueId).getValue());
    }

    @Override
    public Optional<RnibCell> getPrimaryCell(RnibUe ue) {
        // search all links for this UE and find PRIMARY.
        Optional<RnibLink> primary = getLinks().stream()
                .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
                .filter(l -> l.getLinkId().getUe().equals(ue))
                .findFirst();

        return primary.flatMap(l -> Optional.of(l.getLinkId().getCell()));
    }

    @Override
    public Optional<RnibUe> getUe(long ueId) {
        return Optional.ofNullable(ueMap.get(ueId));
    }

    @Override
    public Optional<RnibUe> getUe(ECGI ecgi, CRNTI crnti) {
        return Optional.ofNullable(crntiMap.get(EcgiCrntiPair.valueOf(ecgi, crnti)))
                .flatMap(this::getUe);
    }

    /**
     * Get from HEX string the according ECI class object.
     *
     * @param eciHex HEX string
     * @return ECI object if created successfully
     */
    private EUTRANCellIdentifier hexToEci(String eciHex) {
        byte[] hexBinary = DatatypeConverter.parseHexBinary(eciHex);
        return new EUTRANCellIdentifier(hexBinary, 28);
    }
}
