package com.ecep.contract.vm;

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

import com.ecep.contract.ContractPayWay;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyContract;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractGroup;
import com.ecep.contract.model.ContractKind;
import com.ecep.contract.model.ContractType;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;

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

/**
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class ContractViewModel extends IdentityViewModel<Contract> {
    private SimpleStringProperty guid = new SimpleStringProperty();
    private SimpleObjectProperty<ContractPayWay> payWay = new SimpleObjectProperty<>();

    private SimpleStringProperty code = new SimpleStringProperty();
    private SimpleStringProperty name = new SimpleStringProperty();
    private SimpleStringProperty state = new SimpleStringProperty();
    /**
     * 分组
     */
    private SimpleObjectProperty<ContractGroup> group = new SimpleObjectProperty<>();
    /**
     * 分类
     */
    private SimpleObjectProperty<ContractType> type = new SimpleObjectProperty<>();
    /**
     * 性质
     */
    private SimpleObjectProperty<ContractKind> kind = new SimpleObjectProperty<>();
    /**
     * 主合同编号
     */
    private SimpleStringProperty parentCode = new SimpleStringProperty();
    /**
     * 签订日期
     */
    private SimpleObjectProperty<LocalDate> orderDate = new SimpleObjectProperty<>();
    /**
     * 合同起始日期
     */
    private SimpleObjectProperty<LocalDate> startDate = new SimpleObjectProperty<>();
    /**
     * 合同截止日期
     */
    private SimpleObjectProperty<LocalDate> endDate = new SimpleObjectProperty<>();

    private SimpleObjectProperty<Employee> setupPerson = new SimpleObjectProperty<>();
    private SimpleObjectProperty<LocalDate> setupDate = new SimpleObjectProperty<>();
    /**
     * 生效人
     */
    private SimpleObjectProperty<Employee> inurePerson = new SimpleObjectProperty<>();
    private SimpleObjectProperty<LocalDate> inureDate = new SimpleObjectProperty<>();
    /**
     * 修改人
     */
    private SimpleObjectProperty<Employee> varyPerson = new SimpleObjectProperty<>();
    private SimpleObjectProperty<LocalDate> varyDate = new SimpleObjectProperty<>();

    /**
     * 文件夹
     */
    private SimpleStringProperty path = new SimpleStringProperty();

    private SimpleDoubleProperty amount = new SimpleDoubleProperty();
    private SimpleBooleanProperty standardPayWay = new SimpleBooleanProperty();
    private SimpleBooleanProperty standardContractText = new SimpleBooleanProperty();

    private SimpleStringProperty description = new SimpleStringProperty();
    private SimpleObjectProperty<LocalDateTime> created = new SimpleObjectProperty<>();

    private SimpleObjectProperty<Company> company = new SimpleObjectProperty<>();
    /**
     * 业务员
     */
    private SimpleObjectProperty<Employee> employee = new SimpleObjectProperty<>();
    /**
     * 经办人
     */
    private SimpleObjectProperty<Employee> handler = new SimpleObjectProperty<>();
    /**
     * 项目
     */
    private SimpleObjectProperty<Project> project = new SimpleObjectProperty<>();

    /**
     * 版本
     */
    private SimpleIntegerProperty version = new SimpleIntegerProperty();

    /**
     * 总数量
     */
    private SimpleDoubleProperty totalQuantity = new SimpleDoubleProperty();
    /**
     * 总金额
     */
    private SimpleDoubleProperty totalAmount = new SimpleDoubleProperty();
    /**
     * 总 不含税 金额
     */
    private SimpleDoubleProperty totalUnTaxAmount = new SimpleDoubleProperty();

    /**
     * 已执行数量
     */
    private SimpleDoubleProperty execQuantity = new SimpleDoubleProperty();
    /**
     * 已执行金额
     */
    private SimpleDoubleProperty execAmount = new SimpleDoubleProperty();
    /**
     * 已执行 不含税 金额
     */
    private SimpleDoubleProperty execUnTaxAmount = new SimpleDoubleProperty();

    public static ContractViewModel from(CompanyContract cc) {
        ContractViewModel model = new ContractViewModel();
        model.update(cc.getContract());
        return model;
    }

    public static ContractViewModel from(Contract cc) {
        ContractViewModel model = new ContractViewModel();
        model.update(cc);
        return model;
    }

    public void updateFrom(Contract c) {
        super.updateFrom(c);
        getGuid().set(c.getGuid());
        getPayWay().set(c.getPayWay());
        getCode().set(c.getCode());
        getName().set(c.getName());
        getState().set(c.getState());

        getGroup().set(c.getGroup());
        getType().set(c.getType());
        getKind().set(c.getKind());

        getParentCode().set(c.getParentCode());

        getSetupPerson().set(c.getSetupPerson());
        getSetupDate().set(c.getSetupDate());

        getOrderDate().set(c.getOrderDate());
        getStartDate().set(c.getStartDate());
        getEndDate().set(c.getEndDate());

        getInurePerson().set(c.getInurePerson());
        getInureDate().set(c.getInureDate());

        getVaryPerson().set(c.getVaryPerson());
        getVaryDate().set(c.getVaryDate());

        getCompany().set(c.getCompany());
        getEmployee().set(c.getEmployee());
        getHandler().set(c.getHandler());
        getProject().set(c.getProject());

        path.set(c.getPath());
        description.set(c.getDescription());
        amount.set(Objects.requireNonNullElse(c.getAmount(), 0D));
        standardPayWay.set(c.isStandardPayWay());
        standardContractText.set(c.isStandardPContractText());
        created.set(c.getCreated());
        version.set(c.getVersion());

        getTotalQuantity().set(c.getTotalQuantity());
        getTotalAmount().set(c.getTotalAmount());
        getTotalUnTaxAmount().set(c.getTotalUnTaxAmount());
        getExecQuantity().set(c.getExecQuantity());
        getExecAmount().set(c.getExecAmount());
        getExecUnTaxAmount().set(c.getExecUnTaxAmount());
    }

    public boolean copyTo(Contract contract) {
        boolean modified = super.copyTo(contract);
        if (!Objects.equals(guid.get(), contract.getGuid())) {
            contract.setGuid(guid.get());
            modified = true;
        }
        if (!Objects.equals(payWay.get(), contract.getPayWay())) {
            contract.setPayWay(payWay.get());
            modified = true;
        }
        if (!Objects.equals(code.get(), contract.getCode())) {
            contract.setCode(code.get());
            modified = true;
        }
        if (!Objects.equals(name.get(), contract.getName())) {
            contract.setName(name.get());
            modified = true;
        }
        if (!Objects.equals(state.get(), contract.getState())) {
            contract.setState(state.get());
            modified = true;
        }

        if (!Objects.equals(group.get(), contract.getGroup())) {
            contract.setGroup(group.get());
            modified = true;
        }
        if (!Objects.equals(type.get(), contract.getType())) {
            contract.setType(type.get());
            modified = true;
        }
        if (!Objects.equals(kind.get(), contract.getKind())) {
            contract.setKind(kind.get());
            modified = true;
        }

        if (!Objects.equals(parentCode.get(), contract.getParentCode())) {
            contract.setParentCode(parentCode.get());
            modified = true;
        }

        if (!Objects.equals(setupPerson.get(), contract.getSetupPerson())) {
            contract.setSetupPerson(setupPerson.get());
            modified = true;
        }

        if (!Objects.equals(setupDate.get(), contract.getSetupDate())) {
            contract.setSetupDate(setupDate.get());
            modified = true;
        }

        if (!Objects.equals(orderDate.get(), contract.getOrderDate())) {
            contract.setOrderDate(orderDate.get());
            modified = true;
        }

        if (!Objects.equals(startDate.get(), contract.getStartDate())) {
            contract.setStartDate(startDate.get());
            modified = true;
        }

        if (!Objects.equals(endDate.get(), contract.getEndDate())) {
            contract.setEndDate(endDate.get());
            modified = true;
        }

        if (!Objects.equals(inurePerson.get(), contract.getInurePerson())) {
            contract.setInurePerson(inurePerson.get());
            modified = true;
        }

        if (!Objects.equals(inureDate.get(), contract.getInureDate())) {
            contract.setInureDate(inureDate.get());
            modified = true;
        }

        if (!Objects.equals(varyPerson.get(), contract.getVaryPerson())) {
            contract.setVaryPerson(varyPerson.get());
            modified = true;
        }

        if (!Objects.equals(varyDate.get(), contract.getVaryDate())) {
            contract.setVaryDate(varyDate.get());
            modified = true;
        }

        if (!Objects.equals(path.get(), contract.getPath())) {
            contract.setPath(path.get());
            modified = true;
        }

        if (!Objects.equals(description.get(), contract.getDescription())) {
            contract.setDescription(description.get());
            modified = true;
        }
        if (!Objects.equals(getEmployee().get(), contract.getEmployee())) {
            contract.setEmployee(getEmployee().get());
            modified = true;
        }
        if (!Objects.equals(getHandler().get(), contract.getHandler())) {
            contract.setHandler(getHandler().get());
            modified = true;
        }
        if (!Objects.equals(getCompany().get(), contract.getCompany())) {
            contract.setCompany(getCompany().get());
            modified = true;
        }
        if (!Objects.equals(getProject().get(), contract.getProject())) {
            contract.setProject(getProject().get());
            modified = true;
        }
        if (!Objects.equals(amount.get(), contract.getAmount())) {
            contract.setAmount(amount.get());
            modified = true;
        }
        if (!Objects.equals(standardPayWay.get(), contract.isStandardPayWay())) {
            contract.setStandardPayWay(standardPayWay.get());
            modified = true;
        }
        if (!Objects.equals(standardContractText.get(), contract.isStandardPContractText())) {
            contract.setStandardPContractText(standardContractText.get());
            modified = true;
        }
        if (!doubleEquals(totalQuantity.get(), contract.getTotalQuantity())) {
            contract.setTotalQuantity(totalQuantity.get());
            modified = true;
        }
        if (!doubleEquals(totalAmount.get(), contract.getTotalAmount())) {
            contract.setTotalAmount(totalAmount.get());
            modified = true;
        }
        if (!doubleEquals(totalUnTaxAmount.get(), contract.getTotalUnTaxAmount())) {
            contract.setTotalUnTaxAmount(totalUnTaxAmount.get());
            modified = true;
        }
        if (!doubleEquals(execQuantity.get(), contract.getExecQuantity())) {
            contract.setExecQuantity(execQuantity.get());
            modified = true;
        }
        if (!doubleEquals(execAmount.get(), contract.getExecAmount())) {
            contract.setExecAmount(execAmount.get());
            modified = true;
        }
        if (!doubleEquals(execUnTaxAmount.get(), contract.getExecUnTaxAmount())) {
            contract.setExecUnTaxAmount(execUnTaxAmount.get());
            modified = true;
        }
        if (!Objects.equals(created.get(), contract.getCreated())) {
            contract.setCreated(created.get());
            modified = true;
        }
        return modified;
    }

    private boolean doubleEquals(double a, double b) {
        return Math.abs(a - b) < 0.0001;
    }
}
