package com.gingersoft.gsa.cloud.base.order.cart;

import com.gingersoft.gsa.cloud.base.common.bean.MemberInfo;
import com.gingersoft.gsa.cloud.base.order.bean.discount.CouponDiscountBean;
import com.gingersoft.gsa.cloud.base.order.billItem.BillItem;
import com.gingersoft.gsa.cloud.base.order.billItem.DiscountItem;
import com.gingersoft.gsa.cloud.base.order.commodity.OrderDetail;
import com.gingersoft.gsa.cloud.base.order.discount.CouponDiscount;
import com.gingersoft.gsa.cloud.base.order.discount.MemberDiscount;
import com.gingersoft.gsa.cloud.base.order.discount.MultyDiscount;
import com.gingersoft.gsa.cloud.base.order.discount.NomalDiscount;
import com.gingersoft.gsa.cloud.database.bean.Discount;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import lombok.Getter;
import lombok.Setter;

/**
 * 作者：ELEGANT_BIN
 * 版本：1.6.0
 * 创建日期：2020-09-19
 * 修订历史：2020-09-19
 * 描述: 購物車
 */
@Setter
@Getter
public class ShoppingCart {

    private static ShoppingCart shoppingCart;

    public static ShoppingCart getInstance() {
        if (shoppingCart == null) {
            shoppingCart = new ShoppingCart();
        }
        return shoppingCart;
    }

    /**
     * 商品列表
     */
    protected List<OrderDetail> orderCommodityList = new ArrayList<>();
    /**
     * 賬單項列表
     *
     * @see CopyOnWriteArrayList 賬單計算放在子線程中保證同步問題使用CopyOnWriteArrayList
     */
    protected List<BillItem> billItemList = new ArrayList<>();
    /**
     * 折扣列表
     *
     * @see NomalDiscount
     * @see MemberDiscount
     * @see CouponDiscount
     */
    protected List<MultyDiscount> multyDiscountList;
    /**
     * 服務費
     */
    protected Double serviceCharge;
    /**
     * 賬單小數
     */
    protected Double rounding;
    /**
     * 合計
     */
    protected double wholeAmount = 0.0;
    /**
     * 總金額
     */
    protected double totalAmount = 0.0;

    /**
     * 調整購物車商品數量
     */
    private ShoppingCartNumberChange cartNumberChange = new ShoppingCartNumberChange(orderCommodityList);


    public void changeNumber(int number, OrderDetail orderFood, OrderDetail orderMainFood, int select_Full_start_position, int select_Full_end_position, ShoppingCartNumberChange.OnNumberChangeListener listener) {
        cartNumberChange.changeNumber(number, orderFood, orderMainFood, select_Full_start_position, select_Full_end_position, listener);
    }

    /**
     * 將商品添加到購物車
     *
     * @param commodityList
     */
    public void addCommodityList(List<OrderDetail> commodityList) {
        orderCommodityList.addAll(commodityList);
    }

    /**
     * 將商品添加到購物車
     *
     * @param commodity
     */
    public void addCommodity(OrderDetail commodity) {
        orderCommodityList.add(commodity);
    }

    /**
     * 將商品移出購物車
     *
     * @param commodity
     */
    public void delCommodity(OrderDetail commodity) {
        orderCommodityList.remove(commodity);
    }

    /**
     * 修改商品數量
     *
     * @param commodity
     */
    public void setCommodityNum(OrderDetail commodity, int number) {
        for (OrderDetail c : orderCommodityList) {
            if (c == commodity) {
                c.setNumber(number);
                break;
            }
        }
    }

    /**
     * 添加賬單項
     *
     * @param billItem
     */
    public void addBillItem(BillItem billItem) {
        billItemList.add(billItem);
    }

    /**
     * 添加賬單項
     *
     * @param billItems
     */
    public void addBillItems(List<BillItem> billItems) {
        billItemList.addAll(billItems);
    }

    /**
     * 刪除張單項
     *
     * @param billItem
     */
    public void delBillItem(BillItem billItem) {
        billItemList.remove(billItem);
    }

    /**
     * 添加折扣
     *
     * @param multyDiscount
     */
    public void addMultyDiscount(MultyDiscount multyDiscount) {
        getMultyDiscountList().add(multyDiscount);
    }

    /**
     * 刪除折扣
     *
     * @param multyDiscount
     */
    public void delMultyDiscount(MultyDiscount multyDiscount) {
        getMultyDiscountList().remove(multyDiscount);
    }

    /**
     * 刪除所有折扣
     */
    public void delAllMultyDiscount() {
        List<MultyDiscount> multyDiscountList = getMultyDiscountList();
        boolean result = multyDiscountList.removeAll(multyDiscountList);
        int i = 100;
    }

    /**
     * 刪除所有單折扣
     */
    public void delAllNomalDiscountList(List<NomalDiscount> nomalDiscountList) {
        boolean result = getMultyDiscountList().removeAll(nomalDiscountList);
        int i = 100;
    }

    /**
     * 將普通折扣添加到鏈條中
     *
     * @param discount
     * @return
     */
    public MultyDiscount addNomalDiscountToLinked(MultyDiscount multyDiscounts, Discount discount, int status) {
        MultyDiscount nomalDiscount = new NomalDiscount(discount.getRemark(), status, multyDiscounts, discount);
        return nomalDiscount;
    }

    /**
     * 將會員等級折扣添加到鏈條中
     *
     * @param discount
     * @return
     */
    public MultyDiscount addMemberDiscountToLinked(MultyDiscount multyDiscounts, MemberInfo discount, int status) {
        MultyDiscount memberDiscount = new MemberDiscount(discount.getMemberName(), status, multyDiscounts, discount);
        return memberDiscount;
    }

    /**
     * 將優惠券折扣添加到鏈條中
     *
     * @param discount
     * @return
     */
    public MultyDiscount addCouponDiscountToLinked(MultyDiscount multyDiscounts, CouponDiscountBean discount, int status) {
        MultyDiscount couponDiscount = new CouponDiscount(discount.getName(), status, multyDiscounts, discount);
        return couponDiscount;
    }


    public MultyDiscount createNomalDiscount(Discount discount, int status) {
        MultyDiscount nomalDiscount = new NomalDiscount(discount.getRemark(), status, null, discount);
        return nomalDiscount;
    }

    public MultyDiscount createMemberDiscount(MemberInfo discount, int status) {
        MultyDiscount memberDiscount = new MemberDiscount(discount.getMemberName(), status, null, discount);
        return memberDiscount;
    }

    public MultyDiscount createCouponDiscount(CouponDiscountBean discount, int status) {
        MultyDiscount couponDiscount = new CouponDiscount(discount.getName(), status, null, discount);
        return couponDiscount;
    }

    /**
     * 計算折扣鏈金額
     */
    public double calculateLinkedDiscounts(double money) {
        //折扣集合保存每個已經計算過的折扣
        List<MultyDiscount> multyDiscountArrays = new ArrayList<>();
        //折扣鏈對象
        MultyDiscount multyDiscounts = null;
        for (int i = getMultyDiscountList().size() - 1; i >= 0; i--) {
            MultyDiscount discount = getMultyDiscountList().get(i);
            if (discount instanceof NomalDiscount) {
                multyDiscounts = addNomalDiscountToLinked(multyDiscounts, ((NomalDiscount) discount).getDiscount(), discount.getStatus());
            } else if (discount instanceof MemberDiscount) {
                multyDiscounts = addMemberDiscountToLinked(multyDiscounts, ((MemberDiscount) discount).getMemberDiscount(), discount.getStatus());
            } else if (discount instanceof CouponDiscount) {
                multyDiscounts = addCouponDiscountToLinked(multyDiscounts, ((CouponDiscount) discount).getCouponDiscount(), discount.getStatus());
            }
            multyDiscountArrays.add(multyDiscounts);
        }
        if (money != 0 && multyDiscounts != null) {
            //計算折扣金額
            money = multyDiscounts.calculate(money);
        }
        //更新折扣billItem數據
        updateDiscountBillItem(multyDiscountArrays);
        return money;
    }

    private void updateDiscountBillItem(List<MultyDiscount> multyDiscountArrays) {
        byte discountType = BillItem.NOMAL_DISCOUNT_TYPE;
        for (int i = multyDiscountArrays.size() - 1; i >= 0; i--) {
            MultyDiscount discount = multyDiscountArrays.get(i);
            if (discount instanceof NomalDiscount) {
                discountType = BillItem.NOMAL_DISCOUNT_TYPE;
            } else if (discount instanceof MemberDiscount) {
                discountType = BillItem.MEMBER_DISCOUNT_TYPE;
            } else if (discount instanceof CouponDiscount) {
                discountType = BillItem.COUPON_DISCOUNT_TYPE;
            }
            DiscountItem discountItem = new DiscountItem(discount.getName(), discount.getDiscountMoney(), discount.getStatus(), discountType);
            discountItem.setDiscount(discount);
            billItemList.add(discountItem);
        }
    }

    /**
     * 獲取普通折扣列表
     *
     * @return
     */
    public List<NomalDiscount> getNomalDiscoutByMultyDiscountList() {
        List<NomalDiscount> nomalDiscountList = new ArrayList<>();
        for (MultyDiscount multyDiscount : getMultyDiscountList()) {
            if (multyDiscount instanceof NomalDiscount) {
                nomalDiscountList.add((NomalDiscount) multyDiscount);
            }
        }
        return nomalDiscountList;
    }

    public List<MultyDiscount> getMultyDiscountList() {
        if (multyDiscountList == null) {
            multyDiscountList = new ArrayList<>();
        }
        return multyDiscountList;
    }

    public static void main(String[] args) {

        MultyDiscount multyDiscounts = null;
        ShoppingCart shoppingCart = new ShoppingCart();

        Discount discount = new Discount();
        discount.setRemark("9折");
        discount.setType(1);
        discount.setDiscountValue(10);
        multyDiscounts = shoppingCart.addNomalDiscountToLinked(multyDiscounts, discount, 0);
        shoppingCart.addMultyDiscount(multyDiscounts);

        CouponDiscountBean couponDiscountBean = new CouponDiscountBean();
        couponDiscountBean.setCouponTypeName1("魚屋立減50元券");
        couponDiscountBean.setAmount(50);
        couponDiscountBean.setCouponType((byte) 2);
        multyDiscounts = shoppingCart.addCouponDiscountToLinked(multyDiscounts, couponDiscountBean, 0);
        shoppingCart.addMultyDiscount(multyDiscounts);

        MemberInfo memberInfo2 = new MemberInfo();
        memberInfo2.setMemberName("白金會員20%");
        memberInfo2.setMemberDiscount(20);
        multyDiscounts = shoppingCart.addMemberDiscountToLinked(multyDiscounts, memberInfo2, 0);
        shoppingCart.addMultyDiscount(multyDiscounts);

        double discountAfterMoney = shoppingCart.calculateLinkedDiscounts(200);

        System.out.println("折扣後的金額：" + discountAfterMoney);
    }

    /**
     * 具體支付類需要實現的方法
     */
    public void pay(double money) {

    }

    /**
     * 計算賬單前先重置
     */
    public void resetBeforeBillCalculation() {
        initialization(true);
    }

    public void initialization(boolean reset) {
        if (!reset) {
            if (orderCommodityList != null) {
                orderCommodityList.clear();
            }
            if (multyDiscountList != null) {
                multyDiscountList.clear();
            }
        }
        if (billItemList != null) {
            billItemList.clear();
        }
        serviceCharge = null;
        rounding = null;
        wholeAmount = 0.0;
        totalAmount = 0.0;
    }


}
