package com.tykj.dev.device.confirmcheck.entity.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.objenesis.ObjenesisHelper;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * CheckAreaStatVo.
 *
 * @author Matrix <xhyrzldf@gmail.com>
 * @since 2020/8/15 at 7:20 下午
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Accessors(chain = true)
public class CheckAreaStatVo implements Cloneable {

    /**
     * 地区名
     */
    private String areaName;

    /**
     * 实查数量
     */
    private int actualCount;

    /**
     * 应查数量
     */
    private int supposeCount;

    /**
     * 完成进度 0-待办 ， 1-进行中， 2-已完成
     */
    private int comProgress;

    /**
     * 完成情况 0-无误 1-有异常
     */
    private int comSituation;

    /**
     * 该地区对应的统计账单id
     */
    private int areaStatId;

    /**
     * 该地区对应的详情账单id
     */
    private int areaDetailId;

    public CheckAreaStatVo(CheckAreaStatVo vo) {
        this.areaName = vo.getAreaName();
        this.actualCount = vo.getActualCount();
        this.supposeCount = vo.getSupposeCount();
        this.comProgress = vo.getComProgress();
        if (this.comSituation == 1 || vo.getComSituation() == 1) {
            this.comSituation = 1;
        } else {
            this.comSituation = 0;
        }
        this.areaStatId = vo.getAreaStatId();
        this.areaDetailId = vo.getAreaDetailId();
    }

    public CheckAreaStatVo addSuppose(int supposeCount) {
        this.supposeCount += supposeCount;
        return this;
    }

    public void start() {
        if (this.comProgress !=2){
            this.comProgress = 1;
        }
    }

    public void end() {
        this.comProgress = 2;
    }

    /**
     * 将相同地区的统计数据合并
     *
     * @param other 要合并的地区
     * @return 合并后的新地区数据(深度拷贝出来的新对象)
     * @throws IllegalArgumentException 在合并的地区名不同或者统计账单id不同时会抛出(初始账单合并除外,即this.detailId=0)
     */
    public CheckAreaStatVo reduce(@NotNull CheckAreaStatVo other) {
        if (!this.areaName.equals(other.areaName) || this.areaDetailId != other.areaDetailId) {
            //初始化账单的话则不用抛出异常,将other的detailId赋予即可
            if (this.areaDetailId == 0) {
                this.areaDetailId = other.areaDetailId;
            } else {
                throw new IllegalArgumentException(String.format(
                        "要合并的两个地区统计数据的areaName与areaDetailId必须保持一致，" +
                                "你提供的分别是areaName = %s 与 %s , areaDetailId = %d 与 %d %n",
                        this.areaName, other.areaName, this.areaDetailId, other.areaDetailId));
            }
        }

        if (!this.areaName.equals(other.areaName) || this.areaStatId != other.areaStatId) {
            //初始化账单的话则不用抛出异常,将other的detailId赋予即可
            if (this.areaStatId == 0) {
                this.areaStatId = other.areaStatId;
            } else {
                throw new IllegalArgumentException(String.format(
                        "要合并的两个地区统计数据的areaName与areaStatId必须保持一致，" +
                                "你提供的分别是areaName = %s 与 %s , areaStatId = %d 与 %d %n",
                        this.areaName, other.areaName, this.areaStatId, other.areaStatId));
            }
        }

        CheckAreaStatVo reducedVo = new CheckAreaStatVo(this);
        reducedVo.supposeCount += other.supposeCount;
        reducedVo.actualCount += other.actualCount;
        reducedVo.comProgress = other.comProgress;
        //0 无误 1异常
        if (reducedVo.comSituation == 1 || other.comSituation == 1) {
            reducedVo.comSituation = 1;
        } else {
            reducedVo.comSituation = 0;
        }
        return reducedVo;
    }

    /**
     * 将相同地区的统计数据合并(清洁版)
     * 只会将实际核查的结果添加进去，并不会重复添加期望指标数字
     *
     * @param other 要合并的地区
     * @return 合并后的新地区数据(深度拷贝出来的新对象)
     * @throws IllegalArgumentException 在合并的地区名不同或者统计账单id不同时会抛出(初始账单合并除外,即this.detailId=0)
     */
    @SuppressWarnings("DuplicatedCode")
    public CheckAreaStatVo cleanReduce(@NotNull CheckAreaStatVo other) {
        // 合并的两个对象地区与账单id必须相同
        if (!this.areaName.equals(other.areaName) || this.areaDetailId != other.areaDetailId) {
            //初始化账单的话则不用抛出异常,将other的detailId赋予即可
            if (this.areaDetailId == 0) {
                this.areaDetailId = other.areaDetailId;
            } else {
                throw new IllegalArgumentException(String.format(
                        "要合并的两个地区统计数据的areaName与areaDetailId必须保持一致，" +
                                "你提供的分别是areaName = %s 与 %s , areaDetailId = %d 与 %d %n",
                        this.areaName, other.areaName, this.areaDetailId, other.areaDetailId));
            }
        }

        if (!this.areaName.equals(other.areaName) || this.areaStatId != other.areaStatId) {
            //初始化账单的话则不用抛出异常,将other的detailId赋予即可
            if (this.areaStatId == 0) {
                this.areaStatId = other.areaStatId;
            } else {
                throw new IllegalArgumentException(String.format(
                        "要合并的两个地区统计数据的areaName与areaStatId必须保持一致，" +
                                "你提供的分别是areaName = %s 与 %s , areaStatId = %d 与 %d %n",
                        this.areaName, other.areaName, this.areaStatId, other.areaStatId));
            }
        }

        CheckAreaStatVo reducedVo = new CheckAreaStatVo(this);
        reducedVo.actualCount += other.actualCount;
        reducedVo.comProgress = other.comProgress;
        //0 无误 1异常
        if (reducedVo.comSituation == 1 || other.comSituation == 1) {
            reducedVo.comSituation = 1;
        } else {
            reducedVo.comSituation = 0;
        }
        return reducedVo;
    }

    public CheckAreaStatVo combine(CheckAreaStatVo other, Integer cityStatId) {
        this.areaName = other.getAreaName();
        this.areaStatId = cityStatId;
        this.areaDetailId = 0;
        this.supposeCount += other.getSupposeCount();
        this.actualCount += other.getActualCount();
        this.comProgress = other.getComProgress();
        //0 无误 1异常
        if (this.comSituation == 1 || other.comSituation == 1) {
            this.comSituation = 1;
        } else {
            this.comSituation = 0;
        }
        return this;
    }



    public RevAreaStat reverse(){
        return new RevAreaStat(areaName, actualCount, supposeCount, comProgress, comSituation);
    }
}
