package com.thesis.centralserver.dtos;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.thesis.centralserver.entities.DeviceMode;
import lombok.Data;

@Data
public class DeviceDTO {

    private Long id;

    private String ip;
    private int totalMemory;
    private double remainingMemory;
    private double remainingBattery;
    private double processorSpeed;
    private double processorFree;
    private int currencyUnitsAvailable;
    private double networkBandWidthAvailable;
    private DeviceMode deviceMode;

    @JsonIgnore
    double packetSendReceiveCost;
    private double alpha;
    private double beta;
    private double gamma;

    //TODO:  device should also send task previous payments for the task and earning

    @JsonIgnore
    public double getRemainingMemoryRatio() {
        return remainingMemory / totalMemory;
    }

    @JsonIgnore
    public double getRemainingProessingPowerRatio() {
        return processorFree / processorSpeed;
    }

    @JsonIgnore
    public double getRemainingBatteryRatio() {
        return remainingBattery;
    }

    int log2(double x) {
        return log(x, 2);
    }

    int log(double x, int base) {
        return (int) (Math.log(x) / Math.log(base));
    }

    public double setPacketSendReceiveCost(double dataSize) {
        packetSendReceiveCost = ((dataSize * 8) / networkBandWidthAvailable) * 0.152;
        return packetSendReceiveCost;
    }

    public double calculatePatienceFactor() {
        return getStatusMetric() / (6.64 * (alpha + beta + gamma)); //getStatusMetric() / (100 * (alpha + beta + gamma));
    }

    private double getStatusMetric() {

        return alpha * log2(getRemainingMemoryRatio() * 100)
                + beta * log2(getRemainingBatteryRatio() * 100)
                + gamma * log2(getRemainingProessingPowerRatio() * 100);

    }

    public int calculateInitialSellerOfferPrice(double buyerReservePrice,
                                                double buyerPatienceFactor,
                                                double buyerPacketSendingCost,
                                                double dataSize) {

        double sellerReservePrice = calculateReservePrice();
        double differenceValue = calculateDifferenceValue(buyerReservePrice);
        double sellerPatienceFactor = calculatePatienceFactor();
        setPacketSendReceiveCost(dataSize);

        double sellerShare = (differenceValue - (buyerPatienceFactor * differenceValue) -
                (buyerPatienceFactor * sellerPatienceFactor * packetSendReceiveCost) +
                (buyerPatienceFactor * packetSendReceiveCost) - (buyerPatienceFactor * buyerPacketSendingCost) +
                buyerPacketSendingCost) / (differenceValue - differenceValue * buyerPatienceFactor * sellerPatienceFactor);

        System.out.println("sellerShare:  " + sellerShare);

        return (int) (sellerReservePrice + (sellerShare * differenceValue));

    }

    public double calculateDifferenceValue(double buyerReservePrice) {
        return buyerReservePrice - calculateReservePrice();
    }

    public int calculateReservePrice() {
        return (int) (currencyUnitsAvailable / getStatusMetric());
    }

}
