package com.ecep.contract.vm;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;

import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryCatalog;
import com.ecep.contract.model.Price;
import com.ecep.contract.model.VolumeSize;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = false)
public class InventoryViewModel extends IdentityViewModel<Inventory> {
    private SimpleObjectProperty<InventoryCatalog> catalog = new SimpleObjectProperty<>();
    private SimpleStringProperty code = new SimpleStringProperty();
    private SimpleStringProperty specification = new SimpleStringProperty();
    private SimpleBooleanProperty specificationLock = new SimpleBooleanProperty();
    private SimpleStringProperty name = new SimpleStringProperty();
    private SimpleBooleanProperty nameLock = new SimpleBooleanProperty();

    private SimpleFloatProperty purchaseTaxRate = new SimpleFloatProperty();
    private SimpleDoubleProperty purchasePrice = new SimpleDoubleProperty();
    private SimpleDoubleProperty purchaseTaxPrice = new SimpleDoubleProperty();

    private SimpleFloatProperty saleTaxRate = new SimpleFloatProperty();
    private SimpleDoubleProperty salePrice = new SimpleDoubleProperty();
    private SimpleDoubleProperty saleTaxPrice = new SimpleDoubleProperty();

    private SimpleStringProperty weightUnit = new SimpleStringProperty();
    private SimpleStringProperty sizeUnit = new SimpleStringProperty();
    private SimpleStringProperty volumeUnit = new SimpleStringProperty();
    private SimpleDoubleProperty weight = new SimpleDoubleProperty();
    private SimpleDoubleProperty packagedWeight = new SimpleDoubleProperty();
    private SimpleDoubleProperty sizeLength = new SimpleDoubleProperty();
    private SimpleDoubleProperty sizeWidth = new SimpleDoubleProperty();
    private SimpleDoubleProperty sizeHeight = new SimpleDoubleProperty();
    private SimpleDoubleProperty volume = new SimpleDoubleProperty();
    private SimpleDoubleProperty packagedSizeLength = new SimpleDoubleProperty();
    private SimpleDoubleProperty packagedSizeWidth = new SimpleDoubleProperty();
    private SimpleDoubleProperty packagedSizeHeight = new SimpleDoubleProperty();
    private SimpleDoubleProperty packagedVolume = new SimpleDoubleProperty();

    private SimpleStringProperty unit = new SimpleStringProperty();
    private SimpleObjectProperty<Employee> creator = new SimpleObjectProperty<>();
    private SimpleObjectProperty<LocalDate> createTime = new SimpleObjectProperty<>();
    private SimpleObjectProperty<Employee> updater = new SimpleObjectProperty<>();
    private SimpleObjectProperty<LocalDateTime> updateDate = new SimpleObjectProperty<>();

    private SimpleStringProperty description = new SimpleStringProperty();

    public static InventoryViewModel from(Inventory v) {
        InventoryViewModel model = new InventoryViewModel();
        model.update(v);
        return model;
    }

    @Override
    protected void updateFrom(Inventory v) {
        super.updateFrom(v);
        getCatalog().set(v.getCatalog());
        getCode().set(v.getCode());
        getSpecification().set(v.getSpecification());
        getSpecificationLock().set(v.isSpecificationLock());
        getName().set(v.getName());
        getNameLock().set(v.isNameLock());
        getUnit().set(v.getUnit());

        Price purchasePrice = v.getPurchasePrice();
        getPurchaseTaxRate().set(purchasePrice.getTaxRate());
        getPurchasePrice().set(purchasePrice.getPreTaxPrice());
        getPurchaseTaxPrice().set(purchasePrice.getPostTaxPrice());

        Price salePrice = v.getSalePrice();
        getSaleTaxRate().set(salePrice.getTaxRate());
        getSalePrice().set(salePrice.getPreTaxPrice());
        getSaleTaxPrice().set(salePrice.getPostTaxPrice());

        getWeightUnit().set(v.getWeightUnit());
        getSizeUnit().set(v.getSizeUnit());
        getVolumeUnit().set(v.getVolumeUnit());

        getWeight().set(v.getWeight());
        getPackagedWeight().set(v.getPackagedWeight());

        VolumeSize volumeSize = v.getVolumeSize();
        getSizeLength().set(volumeSize.getLength());
        getSizeWidth().set(volumeSize.getWidth());
        getSizeHeight().set(volumeSize.getHeight());
        getVolume().set(volumeSize.getVolume());

        VolumeSize packagedVolumeSize = v.getPackagedVolumeSize();
        getPackagedSizeLength().set(packagedVolumeSize.getLength());
        getPackagedSizeWidth().set(packagedVolumeSize.getWidth());
        getPackagedSizeHeight().set(packagedVolumeSize.getHeight());
        getPackagedVolume().set(packagedVolumeSize.getVolume());

        getCreator().set(v.getCreator());
        getCreateTime().set(v.getCreateTime());
        getUpdater().set(v.getUpdater());
        getUpdateDate().set(v.getUpdateDate());
        getDescription().set(v.getDescription());

    }

    @Override
    public boolean copyTo(Inventory v) {
        if (v == null)
            return false;

        boolean modified = super.copyTo(v);
        if (!Objects.equals(catalog.get(), v.getCatalog())) {
            v.setCatalog(catalog.get());
            modified = true;
        }
        if (!Objects.equals(code.get(), v.getCode())) {
            v.setCode(code.get());
            modified = true;
        }
        if (!Objects.equals(specification.get(), v.getSpecification())) {
            v.setSpecification(specification.get());
            modified = true;
        }
        if (!Objects.equals(specificationLock.get(), v.isSpecificationLock())) {
            v.setSpecificationLock(specificationLock.get());
            modified = true;
        }
        if (!Objects.equals(name.get(), v.getName())) {
            v.setName(name.get());
            modified = true;
        }
        if (!Objects.equals(nameLock.get(), v.isNameLock())) {
            v.setNameLock(nameLock.get());
            modified = true;
        }
        if (!Objects.equals(unit.get(), v.getUnit())) {
            v.setUnit(unit.get());
            modified = true;
        }

        // price
        Price purchasePrice = v.getPurchasePrice();
        if (!Objects.equals(getPurchaseTaxRate().get(), purchasePrice.getTaxRate())) {
            purchasePrice.setTaxRate(getPurchaseTaxRate().get());
            modified = true;
        }
        if (!Objects.equals(getPurchasePrice().get(), purchasePrice.getPreTaxPrice())) {
            purchasePrice.setPreTaxPrice(getPurchasePrice().get());
            modified = true;
        }
        if (!Objects.equals(getPurchaseTaxPrice().get(), purchasePrice.getPostTaxPrice())) {
            purchasePrice.setPostTaxPrice(getPurchaseTaxPrice().get());
            modified = true;
        }

        Price salePrice = v.getSalePrice();
        if (!Objects.equals(getSaleTaxRate().get(), salePrice.getTaxRate())) {
            salePrice.setTaxRate(getSaleTaxRate().get());
            modified = true;
        }
        if (!Objects.equals(getSalePrice().get(), salePrice.getPreTaxPrice())) {
            salePrice.setPreTaxPrice(getSalePrice().get());
            modified = true;
        }
        if (!Objects.equals(getSaleTaxPrice().get(), salePrice.getPostTaxPrice())) {
            salePrice.setPostTaxPrice(getSaleTaxPrice().get());
            modified = true;
        }

        if (!Objects.equals(getWeightUnit().get(), v.getWeightUnit())) {
            v.setWeightUnit(getWeightUnit().get());
            modified = true;
        }
        if (!Objects.equals(getVolumeUnit().get(), v.getVolumeUnit())) {
            v.setVolumeUnit(getVolumeUnit().get());
            modified = true;
        }
        if (!Objects.equals(getSizeUnit().get(), v.getSizeUnit())) {
            v.setSizeUnit(getSizeUnit().get());
            modified = true;
        }

        if (!Objects.equals(getWeight().get(), v.getWeight())) {
            v.setWeight(getWeight().get());
            modified = true;
        }
        if (!Objects.equals(getPackagedWeight().get(), v.getPackagedWeight())) {
            v.setPackagedWeight(getPackagedWeight().get());
            modified = true;
        }

        VolumeSize volumeSize = v.getVolumeSize();
        if (!Objects.equals(getSizeLength().get(), volumeSize.getLength())) {
            volumeSize.setLength(getSizeLength().get());
            modified = true;
        }
        if (!Objects.equals(getSizeWidth().get(), volumeSize.getWidth())) {
            volumeSize.setWidth(getSizeWidth().get());
            modified = true;
        }
        if (!Objects.equals(getSizeHeight().get(), volumeSize.getHeight())) {
            volumeSize.setHeight(getSizeHeight().get());
            modified = true;
        }
        if (!Objects.equals(getSizeLength().get(), volumeSize.getLength())) {
            volumeSize.setLength(getSizeLength().get());
            modified = true;
        }

        VolumeSize packagedVolumeSize = v.getPackagedVolumeSize();
        if (!Objects.equals(getPackagedSizeHeight().get(), packagedVolumeSize.getHeight())) {
            packagedVolumeSize.setHeight(getPackagedSizeHeight().get());
            modified = true;
        }
        if (!Objects.equals(getPackagedSizeLength().get(), packagedVolumeSize.getLength())) {
            packagedVolumeSize.setLength(getPackagedSizeLength().get());
            modified = true;
        }
        if (!Objects.equals(getPackagedSizeWidth().get(), packagedVolumeSize.getWidth())) {
            packagedVolumeSize.setWidth(getPackagedSizeWidth().get());
            modified = true;
        }
        if (!Objects.equals(getPackagedVolume().get(), packagedVolumeSize.getVolume())) {
            packagedVolumeSize.setVolume(getPackagedVolume().get());
            modified = true;
        }

        // creator or updater
        if (!Objects.equals(creator.get(), v.getCreator())) {
            v.setCreator(creator.get());
            modified = true;
        }
        if (!Objects.equals(createTime.get(), v.getCreateTime())) {
            v.setCreateTime(createTime.get());
            modified = true;
        }
        if (!Objects.equals(updater.get(), v.getUpdater())) {
            v.setUpdater(updater.get());
            modified = true;
        }
        if (!Objects.equals(updateDate.get(), v.getUpdateDate())) {
            v.setUpdateDate(updateDate.get());
            modified = true;
        }

        if (!Objects.equals(description.get(), v.getDescription())) {
            v.setDescription(description.get());
            modified = true;
        }
        return modified;
    }

    void taxPrice2ExclusiveTaxPrice(SimpleDoubleProperty taxPrice, SimpleDoubleProperty exclusiveTaxPrice,
            SimpleFloatProperty taxRate) {
        double value = taxPrice.get();
        exclusiveTaxPrice.setValue(value / ((100 + taxRate.get()) / 100));
    }

    void exclusiveTaxPrice2TaxPrice(SimpleDoubleProperty exclusiveTaxPrice, SimpleDoubleProperty taxPrice,
            SimpleFloatProperty taxRate) {
        double value = exclusiveTaxPrice.get();
        taxPrice.setValue(value * ((100 + taxRate.get()) / 100.0));
    }

    public void updateSalePrice(double v) {
        getSalePrice().set(v);
        exclusiveTaxPrice2TaxPrice(getSalePrice(), getSaleTaxPrice(), getSaleTaxRate());
    }

    public void updateSaleTaxPrice(double v) {
        getSaleTaxPrice().set(v);
        taxPrice2ExclusiveTaxPrice(getSaleTaxPrice(), getSalePrice(), getSaleTaxRate());
    }

    public void updatePurchasePrice(double v) {
        getPurchasePrice().set(v);
        exclusiveTaxPrice2TaxPrice(getPurchasePrice(), getPurchaseTaxPrice(), getPurchaseTaxRate());
    }

    public void updatePurchaseTaxPrice(double v) {
        getPurchaseTaxPrice().set(v);
        taxPrice2ExclusiveTaxPrice(getPurchaseTaxPrice(), getPurchasePrice(), getPurchaseTaxRate());
    }
}
