/*-
 * ============LICENSE_START=======================================================
 * OSAM Core
 * ================================================================================
 * Copyright (C) 2018 Netsia
 * ================================================================================
 * 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.
 * ============LICENSE_END=========================================================
 */



package org.onap.osam.core;

import com.google.common.collect.Lists;
import org.onap.osam.api.service.AccessPodService;
import org.onap.osam.common.exception.AbstractOLTException;
import org.onap.osam.common.exception.InvalidOperationException;
import org.onap.osam.common.exception.NotFoundException;
import org.onap.osam.api.service.DeviceService;
import org.onap.osam.common.exception.ServerException;
import org.onap.osam.external.grpc.AbstractOLTClient;
import org.onap.osam.model.dao.*;
import org.onap.osam.model.repository.ChassisRepository;
import org.onap.osam.model.repository.OLTPortRepository;
import org.onap.osam.model.repository.OLTSlotRepository;
import org.onap.osam.model.repository.ONTDeviceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * Created by Zafer Kaban on 18.09.2018.
 */
@Service
public class DeviceServiceImpl extends AbstractBaseServiceImpl implements DeviceService {

    private ChassisRepository chassisRepository;
    private OLTPortRepository oltPortRepository;
    private OLTSlotRepository oltSlotRepository;
    private ONTDeviceRepository ontDeviceRepository;
    private AbstractOLTClient abstractOLTClient;
    private AccessPodService accessPodService;

    public static int NUMBER_OF_OLT_PORTS   = 16;
    public static int NUMBER_OF_ONT_DEVICES = 64;

    @Autowired
    public DeviceServiceImpl(ChassisRepository chassisRepository,
                             OLTPortRepository oltPortRepository,
                             OLTSlotRepository oltSlotRepository,
                             ONTDeviceRepository ontDeviceRepository,
                             AbstractOLTClient abstractOLTClient,
                             AccessPodService accessPodService) {
        this.chassisRepository = chassisRepository;
        this.oltPortRepository = oltPortRepository;
        this.oltSlotRepository = oltSlotRepository;
        this.ontDeviceRepository = ontDeviceRepository;
        this.abstractOLTClient = abstractOLTClient;
        this.accessPodService = accessPodService;
    }

    @Override
    public Chassis addChassis(Chassis chassis) {
        AccessPod accessPod = accessPodService.findByPnfId(chassis.getAccessPod().getPnfId());
        chassis.setAccessPod(accessPod);
        abstractOLTClient.createChassis(chassis);
        return add(chassis, chassisRepository);
    }

    @Override
    public void deleteChassis(Long id) {
        log.info("Deleting chassis, id: {}", id);
        remove(id, chassisRepository,Chassis.class);
    }

    public void deleteChassisByClli(String clli) {
        Optional<Chassis> chassis = chassisRepository.findByClli(clli);
        if (chassis.isPresent()){
            Long id = chassis.get().getId();
            log.trace("Deleting chassis, clli: {}", clli);
            remove(id, chassisRepository,Chassis.class);
        } else {
            log.error("Chassis not found for clli {}, nothing to delete", clli);
            throw new NotFoundException("Chassis not found for clli {}",clli);
        }
    }

    @Override
    public Chassis getChassisById(Long id) {
        Optional<Chassis> chassis = chassisRepository.findById(id);
        if (!chassis.isPresent()) {
            log.error("Chassis not found for id {}", id);
            throw new NotFoundException("Chassis not found for id {}",id);
        }
        return chassis.get();
    }

    @Override
    public Chassis getChassisByClli(String clli) {
        Optional<Chassis> chassis = chassisRepository.findByClli(clli);
        if (!chassis.isPresent()) {
            log.error("Chassis not found for clli {}", clli);
            throw new NotFoundException("Chassis not found for clli {}",clli);
        }
        return chassis.get();
    }

    @Override
    public Long getChassisCount() {
        return chassisRepository.count();
    }

    @Override
    public List<Chassis> getByPnfId(String pnfId) {
        Optional<List<Chassis>> chassisList = chassisRepository.findByAccessPodPnfId(pnfId);
        if (!chassisList.isPresent()) {
            log.error("Chassis is not found with pnfId {}", pnfId);
            throw new NotFoundException("Chassis is not found with pnfId : {}",pnfId);
        }
        return chassisList.get();
    }

    @Override
    public List<Chassis> getAllChassis() {
        return Lists.newArrayList(chassisRepository.findAll());
    }

    @Override
    public OLTSlot addOLTSlot(OLTSlot oltSlot, Chassis chassis) {
        Set<OLTSlot> oltSlots = Optional.ofNullable(chassis.getOltSlots()).orElse(new HashSet<>());
        int size = oltSlots.size();
        if (size == NUMBER_OF_OLT_PORTS) {
            log.error("Maximum number of OLTs exceeded, max size per chassis: {}", NUMBER_OF_OLT_PORTS);
            throw new InvalidOperationException("Maximum number of OLTs exceeded");
        }
        oltSlot.setNumber(size+1);
        oltSlot.setAdminState(AdminState.ENABLED);
        oltSlot.setOperationalState(ActivityState.ACTIVE);
        oltSlot.setPortAuthState(ActivityState.ACTIVE);
        abstractOLTClient.createOLTChassis(oltSlot);

        oltSlot.setChassis(chassis);
        log.trace("Adding OLT Slot, OLT slot: {}", oltSlot);
        add(oltSlot, oltSlotRepository);
        for (int j = 0; j < 16 ; j++) {
            OLTPort oltPort = new OLTPort();
            oltPort.setOltSlot(oltSlot);
            oltPort.setPortNumber(j+1);
            oltPort.setAdminState(AdminState.ENABLED);
            oltPort.setPortAuthState(ActivityState.ACTIVE);
            log.trace("Adding OLT Port on this slot, OLT port: {}", oltPort);
            add(oltPort, oltPortRepository);
        }
        oltSlots.add(oltSlot);
        chassis.setOltSlots(oltSlots);
        log.trace("Adding this OLT slot to chassis {}", chassis);
        chassisRepository.save(chassis);
        return oltSlot;
    }

    @Override
    public void deleteOLTSlot(Long id) {
        log.info("Deleting OLT slot, id: {}", id);
        oltSlotRepository.deleteById(id);
    }

    @Override
    public OLTSlot getOLTSlotById(Long id) {
        Optional<OLTSlot> oltSlot = oltSlotRepository.findById(id);
        if (!oltSlot.isPresent()) {
            log.error("OLT Slot not found with id {}", id);
            throw new NotFoundException("OLT Slot not found with id "+id);
        }
        return oltSlot.get();
    }

    @Override
    public OLTSlot getOLTSlotBySerialNumber(String serialNumber) {
        Optional<OLTSlot> oltSlot = oltSlotRepository.findBySerialNumber(serialNumber);
        if (!oltSlot.isPresent()) {
            log.error("OLT Slot not found with serial number {}", serialNumber);
            throw new NotFoundException("OLT Slot not found with serialNumber {}",serialNumber);
        }
        return oltSlot.get();
    }

    @Override
    public List<OLTSlot> getAllOLTSlots() {
        return Lists.newArrayList(oltSlotRepository.findAll());
    }

    @Override
    public void deleteOLTPort(Long id) {
        log.info("Deleting OLT port, id: {}", id);
        oltPortRepository.deleteById(id);
    }

    @Override
    public OLTPort getOLTPortById(Long id) {
        Optional<OLTPort> oltPort = oltPortRepository.findById(id);
        if (!oltPort.isPresent()) {
            log.error("OLT Port not found, id: {}", id);
            throw new NotFoundException("OLT Port not found, id {}",id);
        }
        return oltPort.get();
    }

    @Override
    public ONTDevice provisionONTDevice(ONTDevice ont, OntProvisioningType provisioningType){
        log.trace("ONT Device provisioning, ONT Device: {}, provisioning type: ");
        OLTPort oltPort = ont.getOLTPort();
        int portNumber = oltPort.getPortNumber();
        OLTSlot oltSlot = oltPort.getOltSlot();
        int slotNumber = oltSlot.getNumber();
        Chassis chassis = oltSlot.getChassis();
        String clli = chassis.getClli();
        int ontNumber = ont.getNumber();
        String serialNumber = ont.getSerialNumber();
        Optional<OLTPort> thePort = oltPortRepository.findByPortNumberAndOltSlot_NumberAndOltSlot_ChassisClli(portNumber,slotNumber,clli);
        if (thePort.isPresent()) {
            OLTPort port = thePort.get();
            log.trace("Port found : {}", thePort);
            Set<ONTDevice> ontDevices = Optional.ofNullable(port.getOntDevices()).orElse(new HashSet<>());

            ONTDevice ontDevice = new ONTDevice();
            ontDevice.setSerialNumber(serialNumber);
            ontDevice.setNumber(ontNumber);
            ontDevice.setOLTPort(port);
            ontDevice.setAdminState(AdminState.ENABLED);
            ontDevice.setOperationalState(ActivityState.ACTIVE);
            ontDevice.setPortAuthState(ActivityState.ACTIVE);
            ontDevice.setCTag(ont.getCTag());
            ontDevice.setSTag(ont.getSTag());
            ontDevice.setCircuitId(ont.getCircuitId());
            ontDevice.setNasPortId(ont.getNasPortId());

            //TODO Handle technology and speed profiles later
            ontDevice.setSpeedProfile(null);
            ontDevice.setTechProfile(null);

            boolean success =  false;
            if (provisioningType == OntProvisioningType.FULL) {
                success = abstractOLTClient.provisionOntFull(ont);
            } else if (provisioningType == OntProvisioningType.PREPROVISION) {
                success = abstractOLTClient.preProvisionOnt(ont);
            } else {
                success = abstractOLTClient.provisionONT(ont);
            }

            if (success){
                ontDevice = add(ontDevice, ontDeviceRepository);
                ontDevices.add(ontDevice);
                port.setOntDevices(ontDevices);
                oltPortRepository.save(port);
            } else {
                log.error("Failed to process ONTDevice at Abstract OLT, ONTDevice: {}", ont);
                throw new ServerException("Failed to provision ONTDevice with serial number " + ont.getSerialNumber());
            }

        } else {
            log.error("Port not found, port number: {}", portNumber);
            throw new NotFoundException("Port not found, port number {}",portNumber);
        }
        return ont;
    }

    @Override
    public void deleteONTDevice(Long id) {
        log.info("Deleting ONT device port, id: {}", id);
        ontDeviceRepository.deleteById(id);
    }

    @Override
    public ONTDevice getONTDeviceById(Long id) {
        Optional<ONTDevice> ontDevice = ontDeviceRepository.findById(id);
        if (!ontDevice.isPresent()) {
            log.error("Couldn't find ONT Device with ID {}", id);
            throw new NotFoundException("Couldn't find ONT Device with ID {}",id);
        }
        return ontDevice.get();
    }

    @Override
    public ONTDevice getONTDeviceBySerialNumber(String serialNumber) {
        Optional<ONTDevice> ontDevice = ontDeviceRepository.findBySerialNumber(serialNumber);
        if (!ontDevice.isPresent()) {
            log.error("Couldn't find ONT Device with serialNumber {}", serialNumber);
            throw new NotFoundException("Couldn't find ONT Device with serialNumber {}",serialNumber);
        }
        return ontDevice.get();
    }

    @Override
    public List<ONTDevice> getAllONTDevices() {
        return Lists.newArrayList(ontDeviceRepository.findAll());
    }
}
