package com.usoftchina.bi.server.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.usoftchina.bi.server.model.bo.Screen;
import com.usoftchina.bi.server.model.bo.ScreenStr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
解析筛选信息
 */
@Component
public class ScreenUtil {
    @Autowired
    ObjectMapper objectMapper;

    public ScreenStr screensUtil(List<Screen> screenList, String xColumn, String xColumnType) {
        //返回值
        ScreenStr screenStr = new ScreenStr();
        if (screenList.size() == 0) {
            screenStr.setRet("");
            screenStr.setWithColumnRet("");
            return screenStr;
        }
        String ret = "";            //筛选条件
        String withColumnRet = "";   //与目标列相同的筛选条件
        Iterator isList = screenList.iterator();
        while (isList.hasNext()) {
            Screen screen = (Screen) isList.next();
            String columnName = screen.getColumnName();
            String columnType = screen.getColumnType();
            String symbol = screen.getSymbol();
            String value = screen.getValue();

            if (columnType != "time" && !("time".equals(columnType))) {
                String symbVal = getSymbAndVal(symbol, value, columnType);
                if (xColumn.equals(columnName)) {
                    withColumnRet = ret + " and " + columnName + " " + symbVal;
                } else {
                    ret = ret + " and " + columnName + " " + symbVal;
                }
            }
            if (columnType == "time" || "time".equals(columnType)) {
                String symbVal = getTimeSymbAndVal(symbol, value);
                String column = getTimeColumn(columnName, xColumnType);
                if (xColumn.equals(columnName)) {
                    withColumnRet = ret + " and " + column + " " + symbVal;
                } else {
                    ret = ret + " and " + column + " " + symbVal;
                }
            }
        }
        screenStr.setRet(ret);
        screenStr.setWithColumnRet(withColumnRet);
        return screenStr;
    }

    public String getSymbAndVal(String symbol, String value, String columnType) {
        String values = "" + value;
        String tar = "";
        if ("contain".equals(symbol)) {
            if ("categorical".equals(columnType)) {
                tar = "in " + getContainsCate(value);
            } else {
                tar = "like '%" + values + "%'";
            }
        } else if ("notContain".equals(symbol)) {
            if ("categorical".equals(columnType)) {
                tar = "not in " + getContainsCate(value);
            } else {
                tar = "not like '%" + values + "%'";
            }
        } else if ("startsWith".equals(symbol)) {
            tar = "like '" + values + "%'";
        } else if ("endsWith".equals(symbol)) {
            tar = "like '%" + values + "'";
        } else if ("null".equals(symbol)) {
            tar = "is null";
        } else if ("notNull".equals(symbol)) {
            tar = "is not null";
        } else if ("between".equals(symbol)) {
            tar = "";
            String[] str = value.split(",");
            String str1 = str[0];
            String str2 = str[1];
            tar = "between '" + str1 + "' and '" + str2 + "'";
        } else if("notInclude".equals(symbol)) {
            tar = "not like '%" + values + "%'";
        } else if("include".equals(symbol)){
            tar = "like '%" + values + "%'";
        } else if("equals".equals(symbol)){
            tar = "=" + " '" + values + "'";
        } else if("notEquals".equals(symbol)){
            tar = "!=" + " '" + values + "'";
        }else {
            tar = symbol + " '" + values + "'";
        }
        return tar;
    }

    public String getTimeColumn(String columnName, String xColumnType) {
        if ("year".equals(xColumnType)) {
            return "to_char(" + columnName + ", 'yyyy')";
        } else if ("month".equals(xColumnType)) {
            return "to_char(" + columnName + ", 'yyyy-mm')";
        } else if ("day".equals(xColumnType)) {
            return "to_char(" + columnName + ", 'yyyy-mm-dd')";
        } else if ("quarter".equals(xColumnType)) {
            return "to_char(" + columnName + ", 'yyyy-Q')";
        } else if ("week".equals(xColumnType)) {
            return "to_char(" + columnName + ", 'yyyy-ww')";
        } else {
            return "to_char(" + columnName + ", 'yyyy-mm-dd')";
        }
    }

    private String getTimeSymbAndVal(String symbol, String value) {
        String values = "" + value;
        String tar = "";
        if ("between".equals(symbol)) {
            tar = "";
            String[] str = value.split(",");
            String str1 = str[0];
            String str2 = str[1];
            tar = "between '" + str1 + "' and '" + str2 + "'";
        } else if ("=".equals(symbol)) {
            values = TimeFormat(value);
            if (values.contains(",")) {
                String[] str = values.split(",");
                String str1 = str[0];
                String str2 = str[1];
                tar = "between '" + str1 + "' and '" + str2 + "'";
            } else {
                tar = symbol + " '" + values + "'";
            }
        } else {
            tar = symbol + " '" + values + "'";
        }
        return tar;
    }

    public String getContainsCate(String value) {
        List<String> val = new ArrayList<>();
        CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, String.class);
        try {
            val = objectMapper.readValue(value, javaType);   //这里不需要强制转换
        } catch (IOException e) {
            e.printStackTrace();
        }

        String valueString = "";
        Iterator isList = val.iterator();
        while (isList.hasNext()) {
            String v = String.valueOf(isList.next());
            valueString = valueString + ", '" + v + "'";
        }
        valueString = valueString.replaceFirst(",", "(") + ")";
        return valueString;
    }

    /**
     *
     * @return
     */
    private String TimeFormat(String value){
        String formatValue = "";
        LocalDate localDate = LocalDate.now();
        switch (value) {
            case "today" :
                formatValue = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "yesterday" :
                formatValue = localDate.plusDays(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "week" :
                formatValue = localDate.plusWeeks(0).with(DayOfWeek.MONDAY).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusWeeks(0).with(DayOfWeek.SUNDAY).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "lastweek" :
                formatValue = localDate.plusWeeks(-1).with(DayOfWeek.MONDAY).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusWeeks(-1).with(DayOfWeek.SUNDAY).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "month" :
                formatValue = localDate.plusMonths(0).with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusWeeks(0).with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "lastmonth" :
                formatValue = localDate.plusMonths(-1).with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusMonths(-1).with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "quarter" :
                formatValue = quarterStart(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + quarterStart(0).plusMonths(2).with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "lastquarter" :
                formatValue = quarterStart(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + quarterStart(-1).plusMonths(2).with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "halfyear" :
                formatValue = localDate.plusMonths(-6).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "year" :
                formatValue = localDate.plusYears(0).with(TemporalAdjusters.firstDayOfYear()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusYears(0).with(TemporalAdjusters.lastDayOfYear()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            case "lastyear" :
                formatValue = localDate.plusYears(-1).with(TemporalAdjusters.firstDayOfYear()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ","
                        + localDate.plusWeeks(-1).with(TemporalAdjusters.lastDayOfYear()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                break;
            default:
                formatValue = value;
                break;
        }
        return formatValue;
    }

    private static LocalDate quarterStart(int offset) {
        final LocalDate date = LocalDate.now().plusMonths(offset * 3);
        int month = date.getMonth().getValue();//当月
        int start = 0;
        if (month >= 1 && month <= 3) {//第一季度
            start = 1;
        } else if (month >= 4 && month <= 6) {//第二季度
            start = 4;
        } else if (month >= 7 && month <= 9) {//第三季度
            start = 7;
        } else if ((month >= 10 && month <= 12)) {//第四季度
            start = 10;
        } else if (month == 12) {//第四季度
            start = 12;
            month = 14;
        }
        return date.plusMonths(start - month).with(TemporalAdjusters.firstDayOfMonth());
    }
}
