package com.thesis.centralserver.services;

import com.thesis.centralserver.dtos.DeviceDTO;
import com.thesis.centralserver.entities.Device;
import com.thesis.centralserver.entities.DeviceMode;
import com.thesis.centralserver.entities.OffloadingTask;
import com.thesis.centralserver.entities.OffloadingTaskStatus;
import com.thesis.centralserver.entities.mappers.DeviceMapper;
import com.thesis.centralserver.exceptions.NoSellerDeviceFoundException;
import com.thesis.centralserver.repositories.DeviceRepository;
import com.thesis.centralserver.repositories.OffloadingTaskRepository;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DeviceServiceImpl implements DeviceService{

    private final DeviceRepository deviceRepository;
    private final OffloadingTaskRepository offloadingTaskRepository;

    public DeviceServiceImpl(DeviceRepository deviceRepository,
                             OffloadingTaskRepository offloadingTaskRepository) {
        this.deviceRepository = deviceRepository;
        this.offloadingTaskRepository = offloadingTaskRepository;
    }

    @Override
    public Device updateDeviceData(DeviceDTO deviceDTO) {

        // Also if the device is registering for the first time - assign it an initial balance

        if (deviceDTO.getId() == null) {
            deviceDTO.setCurrencyUnitsAvailable(500);
        }

        return deviceRepository.save(DeviceMapper.createDevice(deviceDTO));

    }

    @Override
    public List<Device> getAllDevices() {
        return deviceRepository.findAll();
    }

    @Override
    public OffloadingTask getSellerDevices(double dataSize, DeviceDTO buyerDeviceDTO) throws NoSellerDeviceFoundException {

        OffloadingTask offloadingTask;

        Device buyerDevice = updateDeviceData(buyerDeviceDTO);

        int buyerReservePrice = buyerDeviceDTO.calculateReservePrice();
        double buyerPatienceFactor = buyerDeviceDTO.calculatePatienceFactor();
        double buyerPacketSendingCost = buyerDeviceDTO.setPacketSendReceiveCost(dataSize);

        List<DeviceDTO> filteredSellerDevices = DeviceMapper.createDeviceDTOList(deviceRepository.findByProcessorFreeGreaterThanAndDeviceMode(
                buyerDevice.getProcessorFree(), DeviceMode.SELLER));

        for (DeviceDTO seller : filteredSellerDevices) {

            int sellerReservePrice = seller.calculateReservePrice();

            System.out.println("buyerReservePrice: " + buyerReservePrice);
            System.out.println("sellerReservePrice: " + sellerReservePrice);

            double priceDifference = seller.calculateDifferenceValue(buyerReservePrice);
            if (priceDifference <= 0) {
                //  System.out.println("Shouldn't offload - price difference is negative");
                continue;
            }

            double cost = seller.calculateInitialSellerOfferPrice(buyerReservePrice,
                    buyerPatienceFactor, buyerPacketSendingCost, dataSize);

            if (cost > buyerReservePrice) {
                cost = buyerReservePrice;
            } else if (cost < sellerReservePrice) {
                cost = sellerReservePrice;
            }

            Device sellerDevice = deviceRepository.getOne(seller.getId());

            offloadingTask = new OffloadingTask();
            offloadingTask.setBuyer(buyerDevice);
            offloadingTask.setSeller(sellerDevice);
            offloadingTask.setCost(cost);
            offloadingTask.setStatus(OffloadingTaskStatus.IN_PROGRESS);

            return offloadingTaskRepository.save(offloadingTask);

        }

        throw new NoSellerDeviceFoundException("No seller device found");

    }

}
