<!--  -->
<template>
  <div class="chart-show">
    <header class="chart-header" @click="openNew">
      <span class="chart-title" @click.stop @dblclick="copyText">{{ language === 'ch'?chartInfo.ChartName: chartInfo.ChartNameEn}}</span>
    </header>
    <template v-if="haveData">
      <div
        class="chart-wrapper"
        id="chart-wrapper"
        v-loading="loading"
        element-loading-text="加载中..."
      >
        <chart :options="options" :chartId="chartInfo.ChartInfoId || 0" />
        <div class="mark"></div>
      </div>
    </template>
    <div class="chart-wrapper notfound" v-else>
      <i class="el-icon-warning"></i>哎吆，你的图飞了，赶快去找管理员救命吧~
    </div>
    <div class="bootom-source">
      <strong style="flex:1;" class="text_oneLine">source:  <em> {{language === 'ch' ? chartInfo.ChartSource : chartInfo.ChartSourceEn}}</em></strong>
      <ul class="right-action" @click.stop>
        <li v-if="$route.query.source==='ybxcx'"><collectBtn/></li>
        <li @click="copyUrl" class="copy" v-if="isShare"><i class="el-icon-share"/>分享</li>
        <li @click="refreshChart" v-if="chartInfo.UniqueCode"><i class="el-icon-refresh"/>刷新</li>
      </ul>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';
import _ from 'lodash';
import { useRoute } from 'vue-router';
import chart from '@/components/chart.vue';
import { IState } from './typing';
import { ChartApi } from '@/request/api';
import { IChartType, IDataProps, ILunarItem, IParams, ISeasonDataItemProps } from '@/types';
import Highcharts from 'highcharts';
import { defaultOpts, seasonOptions } from '@/utils/chartOptions';
import moment from 'moment';
import collectBtn from './components/collectBtn.vue'

// 散点x
const scatterXAxis = {
  tickPosition: 'inside',
  lineColor: '#bfbfbf',
  tickColor: '#bfbfbf',
  tickLength:5,
  ordinal: false,
  type: 'linear',
}

//基础y轴
const basicYAxis = {
  tickLength:5,
  lineWidth: 1,
  lineColor: '#bfbfbf',
  tickColor: '#bfbfbf',
  // offset: 0,
  visible: true,
  gridLineWidth: 0,
  tickPosition: 'inside',
  endOnTick: false,
  startOnTick: false,
  showLastLabel: true
}

export default defineComponent({
  components: {
    chart,
    collectBtn
  },
  setup() {
    const route = useRoute();

    const loading = ref(false);

    const haveData = ref(true);

    const code = ref(route.query.code);
    const isShare = ref(route.query.fromType === 'share');
    // 语言 中英文 ch en  默认中文
    const language = ref(route.query.lang || 'ch');
    const screen = ref(document.body.clientWidth < 1200 ? 'phone' : 'pc');

    const state = reactive<IState>({
      options: {},
      chartInfo: {},
      dataList: [],
      sourceName: '',

      /* 奇怪柱形图 */
      barDateList: [],//柱形图的绘图数据
      barXIdData: [],//柱形图的x轴id
      barEdbData: [],//柱形图的表格数据 只用于取值
      chartLimit: {},
      
      /* 商品价格曲线 */
      commodityChartData: [],
      commodityXData: [],
      commodityEdbList: [],
    });

    onMounted((): void => {
      getChartInfo();
    });

    // 打开新窗口
    const openNew = (): void => {
			window.open(window.location.href,'_blank');
    }

    /* 处理图表来源 只限第三方 */
    const dealSourceHandle = (): void => {

      // 取出第三方来源 
      const arr = state.dataList.filter(item => item.EdbType === 1 && item.Source!== 9).map(item => ({
          key: item.Source,
          name: item.SourceName,
        })
      );

      let res_arr = arr.length ? _.uniqBy(arr,'key') : [];

      let str = '';
      res_arr.forEach((item: any) => {
        str += `${item.name}, `
      })
      state.sourceName = str;
    }

    /* 获取图表数据信息 */
    const getChartInfo = async (type='') => {

      if(!code.value) {
        haveData.value = false; 
        return
      } 

      loading.value = true;
      try {
        const { Data } = await ChartApi.getChart({
          UniqueCode: code.value || '',
        });
        loading.value = false;
        state.chartInfo = Data.ChartInfo;
        state.dataList = Data.ChartInfo.Source === 1 ? Data.EdbInfoList : [Data.EdbInfoList[0]];

        //处理英文研报英文设置不全就展示中文
        setLangFromEnReport();
        document.title = language.value==='ch'?Data.ChartInfo.ChartName:Data.ChartInfo.ChartNameEn;

        //eta图
        if(Data.ChartInfo.Source === 1) {
          const typeMap = {
            7: initBarData,
            10: initSectionScatterData
          }
          typeMap[state.chartInfo.ChartType] ? typeMap[state.chartInfo.ChartType](Data) : setOptions();
        }

        const sourceTypeMap = {
          2: initCommodityData,
          3: initRelevanceChartData,
          4: initRelevanceChartData,
          5: initCommodityData,
          6: initFittingEquation
        }
        sourceTypeMap[Data.ChartInfo.Source] && sourceTypeMap[Data.ChartInfo.Source](Data);
        
        haveData.value = true;
        type === 'refresh' && ElMessage.success('刷新成功');
      }catch (e) {
        loading.value = false;
        haveData.value = false; 
      }

    };

    /* 相关性图表 */
    const initRelevanceChartData=(data)=>{
      const relevanceUnitEnMap={
        '年': 'Year',
        '季': 'Season',
        '月': 'Month',
        '周': 'Week',
        '天': 'Day',
      }
      // 处理X轴
      let xAxis={
        categories: data.ChartInfo.Source===3 ? data.XEdbIdValue : data.DataResp.XDateTimeValue,
        tickWidth: 1,
        title: {
          text: data.ChartInfo.Source===3 ? (language.value=='ch'?`期数（${data.CorrelationChartInfo.LeadUnit}）`:`stage（${relevanceUnitEnMap[data.CorrelationChartInfo.LeadUnit]}）`):null,
          align: 'high',
          rotation: 0,
          x: 0,
          y:10,
          offset: 20,
        },
        tickInterval: 1,
        offset:0,
        tickmarkPlacement:'on'
      }

      // 处理Y轴
      let yAxis={
        ...basicYAxis,
        title: {
          text: language.value=='ch'?'相关性系数':'Correlation coefficient',
          align: 'high',
          rotation: 0,
          y: -15,
          offset: 0,
        },
        labels: {
          formatter: function (ctx) {
            let val = ctx.value;
            return val;
          },
          align: 'center',
        },
        min: -1,
        max: 1,
        opposite: false,
        tickWidth: 1,
        tickInterval:0.2,
      }

      //处理series
      let seriesData=[]
      data.YDataList.forEach(item=>{
        let serie_item = {
          data: item.Value,
          type: 'spline',
          yAxis: 0,
          name: language.value=='ch'?data.ChartInfo.ChartName:data.ChartInfo.ChartNameEn,
          color: item.Color,
          chartType: 'linear',
          lineWidth: 3,
          marker: {
            enabled: false
          }
        };
        seriesData.push(serie_item)
      })

      const { LeadValue,LeadUnit } = data.CorrelationChartInfo;
      let tooltip = {

        formatter: function() {
          const that:any = this;
          let str='';
          if(language.value=='ch'){
            str = `<p>相关性系数：${that.y.toFixed(4)}</p><br><p>领先${ data.ChartInfo.Source===3 ?that.x+'期' : LeadValue+LeadUnit}</p>`
          }else{
            str = `<p>Correlation coefficient：${that.y.toFixed(4)}</p><br><p>lead${ data.ChartInfo.Source===3 ? that.x+'stage' : LeadValue+relevanceUnitEnMap[LeadUnit]}</p>`
          }
          
          return str
        },
      }

      state.options = {
        isRelevanceChart:data.ChartInfo.Source===3,
        title: {
          text:'',
        },
        series: seriesData,
        yAxis: [yAxis] ,
        xAxis:xAxis,
        tooltip
      }
    }

    /* 拟合方程曲线 */
    const initFittingEquation = (data) => {
      state.dataList = [data.DataResp];
      setDefaultLineOptions();
    }


    /* 散点截面图 */
    const sectionScatterData = ref<any>({});
    const initSectionScatterData = (data: { DataResp:any,EdbInfoList:any[] }) => {
      sectionScatterData.value = data.DataResp;

      state.chartLimit.min=Number(data.DataResp.YMinValue)
      state.chartLimit.max=Number(data.DataResp.YMaxValue)
      state.chartLimit.x_min=Number(data.DataResp.XMinValue)
      state.chartLimit.x_max=Number(data.DataResp.XMaxValue)

      //校验英文名称是否完整
      if(route.query.fromPage === 'en' && language.value==='en') {
        const { XNameEn,XUnitNameEn,YNameEn,YUnitNameEn,DataList } = data.DataResp;
        let isAllEn = true;
        if(!XNameEn || !XUnitNameEn || !YNameEn || !YUnitNameEn) isAllEn = false;
        if(DataList.some(_ => !_.NameEn)) isAllEn = false;
        console.log(isAllEn)
        language.value = isAllEn ? 'en' : 'ch';
      }

      setSectionScatterChart()
    }
    /* 截面散点图设置 sectionScatterData */
    const setSectionScatterChart = () => {
        const { chartLimit } = state;
        const { DataList,XName,XNameEn,XUnitName,XUnitNameEn,YName,YNameEn,YUnitName,YUnitNameEn } = sectionScatterData.value;
        const { min,max,x_min,x_max }  = chartLimit;

        //y轴
        let yAxis = {
            ...basicYAxis,
            title: {
                text: language.value === 'ch' ? YName : YNameEn,
                align: 'middle',
            },
            opposite: false,
            reversed: false,
            min: Number(min),
            max: Number(max),
            tickWidth: 1,
        }

        //x轴
        let xAxis = {
            ...scatterXAxis,
            title: {
                text: language.value === 'ch' ? XName : XNameEn,
                align: 'middle',
            },
            min: Number(x_min),
            max: Number(x_max),
        }

        //数据列
        let series: any[] = [];
        DataList.forEach(item => {
            //数据列
            let series_item = {
                data: [] as any[],
                type: 'scatter',
                name: language.value === 'ch' ? item.Name : item.NameEn,
                color: item.Color,
                lineWidth: 0,
                chartType: 'linear',
                zIndex:1,
                visible: true
            }
            item.EdbInfoList.forEach(_ => {
                series_item.data.push({
                x: _.XValue,
                y: _.YValue,
                dataLabels: {
                    enabled: _.IsShow,
                    allowOverlap: true,
                    align: 'left',
                    format: language.value === 'ch' ? _.Name : _.NameEn
                }
                })
            })
            series.push(series_item);

        //趋势线
        if(item.ShowTrendLine)  {
            
            let trend_data = item.TrendLimitData.map((_,_index) => (
                _index === item.TrendLimitData.length-1 ? {
                    x: _.X,
                    y: _.Y,
                    dataLabels: {
                      enabled: item.ShowRSquare || item.ShowFitEquation,
                      align: 'left',
                      color: '#666',
                      x: 20,
                      y: 30,
                      zIndex: 9,
                      allowOverlap: true,
                      formatter: function(){
                          let tag = '';
                          item.ShowRSquare && item.ShowFitEquation
                          ? tag =`<span>${item.TrendLine}</span><br><span>R²=${item.RSquare}</span>`
                          : item.ShowRSquare && !item.ShowFitEquation
                          ? tag =`<span>R²=${item.RSquare}</span>`
                          : item.ShowFitEquation && !item.ShowRSquare
                          ? tag =`<span>${item.TrendLine}</span>`
                          : ''
                          return tag
                      }
                    }
                } : {
                    x: _.X,
                    y: _.Y,
                }
            ))

            let trend_item = {
                data: trend_data,
                type: 'spline',
                linkedTo: ':previous',
                color: item.Color,
                lineWidth: 1,
                chartType: 'linear',
                enableMouseTracking: false,
                dashStyle:'Dash',
                zIndex: 2,
                visible: true,
                marker: {
                    enabled: false
                }
            }
            series.push(trend_item)
        }
        })

        let tooltip = {
            formatter: function() {
                const that:any = this;
                let str = '';
                if(language.value === 'ch') {
                  let series_obj = DataList.find(_ => _.Name === that.series.name);
                  let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===that.x && _.YValue===that.y);
  
                  str=`<b>${ ponit_obj.Name }</b>`;
                  str += `<br><span style="color:${that.color}">\u25CF</span>${ponit_obj.XName}: ${that.x} ${ponit_obj.XDate}<br>`;
                  str += `<span style="color:${that.color}">\u25CF</span>${ponit_obj.YName}: ${that.y} ${ponit_obj.YDate}`;
                }else {
                  let series_obj = DataList.find(_ => _.NameEn === that.series.name);
                  let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===that.x && _.YValue===that.y);

                  str=`<b>${ ponit_obj.NameEn }</b>`;
                  str += `<br><span style="color:${that.color}">\u25CF</span>${ponit_obj.XNameEn}: ${that.x} ${ponit_obj.XDate}<br>`;
                  str += `<span style="color:${that.color}">\u25CF</span>${ponit_obj.YNameEn}: ${that.y} ${ponit_obj.YDate}`;

                }
                return str
            }
        }
        
        state.options = {
            title: {
                text:''
            },
            series,
            yAxis: [yAxis],
            xAxis,
            tooltip
        }
    }


    //处理英文研报的图表英文设置不全的情况
    const setLangFromEnReport = () => {
      //来源于英文研报
      if(route.query.fromPage !== 'en') return
      let is_name_en = state.chartInfo.ChartNameEn ? true : false;//名称是否有英文
      let is_target_en = [2,9].includes(state.chartInfo.ChartType) ? true : state.dataList.every(_ => _.EdbNameEn);//指标是否有英文
      console.log(is_name_en,is_target_en)
      language.value = (is_name_en && is_target_en) ? 'en' : 'ch';
    }

    // 曲线图x轴显示计算年限差 >1年 显示年/月 <=1 显示月/日
    const xTimeDiffer = () => {
      const end_date = state.chartInfo.DateType === 5
        ? state.chartInfo.EndDate
        : state.chartInfo.DateType === 6
        ? new Date()
        : '';
      //年限差
      const year_differ = moment(end_date).diff(
        moment(state.chartInfo.StartDate),
        'years',
        true
      );
      // console.log(year_differ)
      if ([5, 6].includes(state.chartInfo.DateType) && year_differ <= 1) {
        return true
      } else {
        return false
      }
    }

    /* 曲线图 */
    const setDefaultLineOptions = () => {
      const { dataList,chartInfo } = state;

      //拼接标题 数据列
      let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
      let rightTwoIndex = dataList.findIndex(item => item.IsAxis ===2);
      // const chartData = _.cloneDeep(dataList);
       //有右二轴时排个序 按照左 右 右2的顺序
      let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);
      
      chartData.forEach((item:IDataProps ,index:number) => {

        //轴位置值相同的下标
        let sameSideIndex = chartData.findIndex(
          (i:IDataProps) => i.IsAxis === item.IsAxis
        );

        //y轴
        let textEn = item.Unit?item.UnitEn:''
        let yItem = {
          ...basicYAxis,
          labels: {
            formatter: function (ctx: any) {
              let val = ctx.value;
              return sameSideIndex !== index ? '' : val;
            },
            align: 'center',
            x: [0,2].includes(item.IsAxis) ? 5 : -5,
            style: {
              fontSize: '10px',
            },
          },
          title: {
            text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
            // text: null,
            align: 'high',
            rotation: 0,
            y: -15,
            x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
            textAlign: item.IsAxis===1 ? 'left' : 'right',
            reserveSpace: false
          },
          opposite: [0,2].includes(item.IsAxis),
          reversed: item.IsOrder,
          min: Number(chartData[sameSideIndex].MinData),
          max: Number(chartData[sameSideIndex].MaxData),
          tickWidth: sameSideIndex !== index ? 0 : 1,
          visible: sameSideIndex === index
        }

        // //拼接标题 判断相同指标名称拼接来源
        let dynamic_title = item.EdbName;
        let dynamic_arr = chartData.filter(
          (item: IDataProps) => dynamic_title === item.EdbName
        );

        // 拼接配置  IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
        let dynamic_tag = concatDynamicTag(item)
        // 英文后缀
        let dynamic_tag_en = concatDynamicTag(item,'en')
        //数据列
        let nameCh:String = dynamic_arr.length > 1
              ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
              : `${item.EdbName}${dynamic_tag}`
        let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
        let name :String=language.value == 'ch'?nameCh:nameEn

        //预测指标配置
        let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item) : {};

        let obj = {
          data: [] as any[],
          type:  'spline',
          yAxis: sameSideIndex,
          name,
          color: item.ChartColor,
          lineWidth: Number(item.ChartWidth),
          ...predict_params
        };
        item.DataList = item.DataList || []
        for (let i of item.DataList) {
          obj.data.push([i.DataTimestamp, i.Value]);
        }

        if(item.DataList.length){
            minTimeArr.push(item.DataList[0].DataTimestamp)
            maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
        }

        data.push(obj);
        ydata.push(yItem);
      })

      // 范围为1年内 x轴显示为月/日 否则默认年/月
      let xAxis:any = {};
      const bool_time:boolean = xTimeDiffer();
      let minTime: number=Math.min(...minTimeArr);
      let maxTime=Math.max(...maxTimeArr);

      let step = setXaxisStep(maxTime-minTime);

      xAxis = bool_time ? {
        ...defaultOpts.xAxis,
        tickInterval: screen.value === 'phone' ? step : undefined,
        labels: {
          formatter: function (ctx: any) {
            return Highcharts.dateFormat('%m/%d', ctx.value);
          },
          style: {
            fontSize: '10px',
          },
        }
      } : {
        ...defaultOpts.xAxis,
        tickInterval: screen.value === 'phone' ? step : undefined,
        labels: {
          style: {
            fontSize: '10px',
          },
        },
      }

      state.options = {
        series: data,
        yAxis: ydata,
        xAxis
      };
    }

    /* 设置x轴步长 刻度数量多一点 */
    const setXaxisStep = (timestamp: number) => {
      // return  timestamp / 6 < 24 * 3600 * 1000 * 30 ? 24 * 3600 * 1000 * 30 : timestamp / 6;
      return  timestamp / 6;
    }

    /* 指标顺序调整  IsAxis: 0右轴 1左轴 2右2*/
    const changeEdbOrder = (data: any[]) => {
      // 左轴指标
      let left_edbs = data.filter(_ => _.IsAxis===1);
      //右轴指标
      let right_edbs = data.filter(_ => !_.IsAxis);
      // 右2轴指标
      let right_two_edbs = data.filter(_ => _.IsAxis === 2);
      // 按 左 右 右2顺序排列
      return [left_edbs,right_edbs,right_two_edbs].flat(Infinity);
    }

    /* 堆叠图/组合图设置  
    本来和曲线图逻辑基本一致兼容下即可 为了以后便于维护和阅读还是拆开写吧
     */
    const setStackOrCombinChart = () => {
      const { dataList,chartInfo } = state;

      //拼接标题 数据列
      let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
      // const chartData = _.cloneDeep(dataList);
      //有右二轴时排个序 按照左 右 右2的顺序
      let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);

      //支持的图表类型
      const chartTypeMap: IChartType  = {
        3: 'areaspline',
        4: 'column',
        6: ''
      };
      let chartStyle = chartTypeMap[chartInfo.ChartType];
      
      chartData.forEach((item:IDataProps ,index:number) => {

        //轴位置值相同的下标
        let sameSideIndex = chartData.findIndex(
          (i:IDataProps) => i.IsAxis === item.IsAxis
        );
        
         //堆叠图的yAxis必须一致 数据列所对应的y轴
        let serie_yIndex = index;
        if([3,4].includes(chartInfo.ChartType)) {
          // 类型为堆叠图时公用第一个指标y轴 
          serie_yIndex =  0;
        } else if(chartInfo.ChartType ===6 && ['areaspline','column'].includes(item.ChartStyle)) {
          // 组合图找第一个堆叠柱状或面积的作为公用
          serie_yIndex = chartData.findIndex((i:IDataProps) => i.ChartStyle === item.ChartStyle);
        }
        //数据对应的y轴是公用轴则配置也共享
        item.IsAxis = serie_yIndex === index ? item.IsAxis : chartData[serie_yIndex].IsAxis;
        item.IsOrder = serie_yIndex === index ? item.IsOrder : chartData[serie_yIndex].IsOrder;

        // 右2轴下标
        let rightTwoIndex = [3,4].includes(chartInfo.ChartType) 
        ? -1
        : dataList.findIndex(item => item.IsAxis===2);

        //y轴
        let textEn = item.Unit?item.UnitEn:''
        let yItem = {
          ...basicYAxis,
          labels: {
            formatter: function (ctx: any) {
              let val = ctx.value;
              return sameSideIndex !== index ? '' : val;
            },
            align: 'center',
            x: [0,2].includes(item.IsAxis) ? 5 : -5,
            style: {
              fontSize: '10px',
            },
          },
          title: {
            text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
            // text: null,
            align: 'high',
            rotation: 0,
            y: -15,
            x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
            textAlign: item.IsAxis===1 ? 'left' : 'right',
            reserveSpace: false
          },
          opposite: [0,2].includes(item.IsAxis),
          reversed: item.IsOrder,
          min: Number(chartData[sameSideIndex].MinData),
          max: Number(chartData[sameSideIndex].MaxData),
          tickWidth: sameSideIndex !== index ? 0 : 1,
          visible: serie_yIndex === index && sameSideIndex ===index
        }

        // //拼接标题 判断相同指标名称拼接来源
        let dynamic_title = item.EdbName;
        let dynamic_arr = chartData.filter(
          (item: IDataProps) => dynamic_title === item.EdbName
        );

        // 拼接配置  IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
        let dynamic_tag = concatDynamicTag(item)
        // 英文后缀
        let dynamic_tag_en = concatDynamicTag(item,'en')
        //数据列
        let nameCh:String = dynamic_arr.length > 1
              ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
              : `${item.EdbName}${dynamic_tag}`
        let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
        let name :String=language.value == 'ch'?nameCh:nameEn

        //预测指标配置
        let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item,chartStyle) : {};

        let obj = {
          data: [] as any[],
          type: chartStyle || item.ChartStyle,
          yAxis: serie_yIndex,
          name,
          color: item.ChartColor,
          lineWidth: (chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? Number(item.ChartWidth) : 0,
          fillColor: (chartInfo.ChartType === 3 || (chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
          zIndex: (chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? 1 : 0, //防止组合图曲线被遮住
          borderWidth: 1,
          borderColor: item.ChartColor,
          ...predict_params
        };
        item.DataList = item.DataList || []
        for (let i of item.DataList) {
          obj.data.push([i.DataTimestamp, i.Value]);
        }

        if(item.DataList.length){
            minTimeArr.push(item.DataList[0].DataTimestamp)
            maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
        }

        data.push(obj);
        ydata.push(yItem);
      })

      // 范围为1年内 x轴显示为月/日 否则默认年/月
      let xAxis:any = {};
      const bool_time:boolean = xTimeDiffer();
      let minTime: number=Math.min(...minTimeArr);
      let maxTime=Math.max(...maxTimeArr);

      let step = setXaxisStep(maxTime-minTime);

      xAxis = bool_time ? {
        ...defaultOpts.xAxis,
        tickInterval: screen.value === 'phone' ? step : undefined,
        labels: {
          formatter: function (ctx: any) {
            return Highcharts.dateFormat('%m/%d', ctx.value);
          },
          style: {
            fontSize: '10px',
          },
        }
      } : {
        ...defaultOpts.xAxis,
        tickInterval: screen.value === 'phone' ? step : undefined,
        labels: {
          style: {
            fontSize: '10px',
          },
        },
      }

      state.options = {
        series: data,
        yAxis: ydata,
        xAxis
      };
    }

    /* 季节图 */
    const setSeasonOptions = () => {
      const chartData = state.dataList[0];
      let seasonYdata:any[] = [],
        seasonData:any[] = [],
        chart = {
          spacing: [5, 8, 2, 8],
        };

      /* 公历数据处理 处理数据列 y轴 */
      if (state.chartInfo.Calendar === '公历')
        for (let j of chartData.DataList) {
          //预测指标配置
          let predict_params =  chartData.EdbInfoCategoryType === 1 ? getSeasonPredictParams(j.CuttingDataTimestamp) : {};

          let serie_item = {
            data: [] as any[],
            type: chartData.ChartStyle,
            yAxis: 0,
            name: j.Year,
            ...predict_params
          };
          const data_array = _.cloneDeep(j.DataList);
          data_array &&
            data_array.forEach((item: IParams) => {
              serie_item.data.push([item.DataTimestamp, item.Value]);
            });
          const index = chartData.DataList.findIndex(
            (item: ISeasonDataItemProps) => item.Year === j.Year
          );
          let textEn = chartData.Unit?chartData.UnitEn:''
          const s_yItem = {
            labels: {
              formatter: function (ctx: any) {
                let val = ctx.value;
                return index !== 0 ? '' : val;
              },
              align: 'center',
              style: {
                fontSize: '10px',
              },
              x: -5,
            },
            title: {
              text:language.value=='ch'?`${chartData.Unit}`:textEn,
              // text: null,
              align: 'high',
              rotation: 0,
              y: -15,
              offset: -(10 * chartData.Unit.length),
            },
            max: Number(chartData.MaxData),
            min: Number(chartData.MinData),
            ...defaultOpts.yAxis,
          };
          seasonData.push(serie_item);
          seasonYdata.push(s_yItem);
        }

      /* 农历数据处理  */
      let filterArr =
        state.chartInfo.Calendar === '农历'
          ? chartData.DataList.List.filter(
              (item: ILunarItem, index: number) => index > 0
            )
          : [];
      if (state.chartInfo.Calendar === '农历')
        for (let j of filterArr) {
           //预测指标配置
          let predict_params =  chartData.EdbInfoCategoryType === 1 ? getSeasonPredictParams(j.CuttingDataTimestamp) : {};

          let serie_item = {
            data: [] as any[],
            type: chartData.ChartStyle,
            yAxis: 0,
            name: j.Year,
            ...predict_params
          };
          const data_array = _.cloneDeep(j.Items);
          data_array &&
            data_array.forEach((item: IParams) => {
              serie_item.data.push([item.DataTimestamp, item.Value]);
            });
          const index = filterArr.findIndex(
            (item: ILunarItem) => item.Year === j.Year
          );
          let textEn = chartData.Unit?chartData.UnitEn:''
          const s_yItem = {
            labels: {
              formatter: function (ctx: any) {
                let val = ctx.value;
                return index !== 0 ? '' : val;
              },
              align: 'center',
              style: {
                fontSize: '10px',
              },
              x: -5,
            },
            title: {
              text:language.value=='ch'?`${chartData.Unit}`:textEn,
              // text: null,
              align: 'high',
              rotation: 0,
              y: -15,
              offset: -(10 * chartData.Unit.length),
            },
            max: Number(chartData.MaxData),
            min: Number(chartData.MinData),
            ...defaultOpts.yAxis,
          };
          seasonData.push(serie_item);
          seasonYdata.push(s_yItem);
        }

      // 季节图x轴显示月/日 周度指标额外处理时间轴显示
      const xAxis = {
        ...defaultOpts.xAxis,
        tickInterval:  screen.value === 'phone' ? 24 * 3600 * 1000 * 60 : undefined,
        labels: {
          formatter: function (ctx: any) {
            return Highcharts.dateFormat('%m/%d', ctx.value);
          },
          style: {
            fontSize: '10px',
          },
        },
      };

      // 季节图提示框显示 月/日
      defaultOpts.tooltip = {
        split: false,
        shared: true,
        dateTimeLabelFormats: {
          // 时间格式化字符
          day: '%m/%d',
          week: '%m/%d',
          month: '%m/%d',
          year: '%m/%d',
        },
        xDateFormat: '%m/%d',
        // valueDecimals: 2,
      };

      //农历默认选中一年数据并隐藏按钮  公历显示全部数据
      let rangeSelector = state.chartInfo.Calendar === '农历'
        ? {
            enabled: true,
            selected: 0,
            inputStyle: {
              display: 'none',
            },
            labelStyle: {
              display: 'none',
            },
            buttonTheme: {
              style: {
                display: 'none',
              },
            },
            buttons: [
              {
                type: 'month',
                count: 12,
                text: '12月',
              },
              {
                type: 'month',
                count: 15,
                text: '15月',
              },
              {
                type: 'all',
                text: '全部',
              },
            ],
          }
        : {
            enabled: false,
          };

      state.options = {
        colors:
          state.chartInfo.Calendar === '公历'
            ? seasonOptions.colors.slice(-chartData.DataList.length)
            : seasonOptions.colors.slice(-filterArr.length),
        series: seasonData,
        yAxis: seasonYdata,
        xAxis,
        rangeSelector,
        chart
      };
    }

    /* 散点图 第一个指标值为x轴 第二个指标为y轴*/
    const setScatterChartOptions = () => {
      const { dataList,chartInfo } = state;

      // 取2个指标中日期相同的数据
      const real_data: any[] = [];
      let tmpData_date: any = {};//用来取点对应的日期
      let data1 =  _.cloneDeep(dataList)[0].DataList || [];
      let data2 =  _.cloneDeep(dataList)[1].DataList || [];
      data1.forEach((_item: IParams) => {
        data2.forEach((_item2: IParams) => {
          if(_item.DataTimestamp === _item2.DataTimestamp) {
            //日期
            let itemIndex =_item.Value + "_" +_item2.Value
            if(tmpData_date[itemIndex]) {
              tmpData_date[itemIndex].push( moment(_item.DataTimestamp).format('YYYY/MM/DD'))
            } else {
              tmpData_date[itemIndex] = [moment(_item.DataTimestamp).format('YYYY/MM/DD')]
            }
            
            //值
            real_data.push({
              x: _item.Value,
              y: _item2.Value
            })
          }
        })
      })
      real_data.sort((x,y) => x-y);

      //悬浮窗 拼接日期 原始指标名称
      let tooltip = {
        formatter: function() {
          const that: any = this;
          return language.value=='ch'?
          `<strong>${ tmpData_date[that.x+'_'+that.y].length > 4 ? tmpData_date[that.x+'_'+that.y].slice(0,4).join()+'...' : tmpData_date[that.x+'_'+that.y].join() }</strong><br>
          ${dataList[0].EdbName}: <span style="font-weight: 600">	${that.x}</span><br>
          ${dataList[1].EdbName}: <span style="font-weight: 600">	${that.y}</span>
          `:
          `<strong>${ tmpData_date[that.x+'_'+that.y].length > 4 ? tmpData_date[that.x+'_'+that.y].slice(0,4).join()+'...' : tmpData_date[that.x+'_'+that.y].join() }</strong><br>
          ${dataList[0].EdbNameEn}: <span style="font-weight: 600">	${that.x}</span><br>
          ${dataList[1].EdbNameEn}: <span style="font-weight: 600">	${that.y}</span>
          `
        }
      }

      const { IsOrder,ChartColor } = dataList[0];
      //y轴
      let yAxis = {
        title: {
          text: language.value=='ch'?`${dataList[1].Unit}`:dataList[1].Unit?dataList[1].UnitEn:'',
          // text: null,
          align: 'high',
          rotation: 0,
          y: -5,
          offset: -(10 * dataList[1].Unit.length),
        },
        labels: {
          formatter: function (ctx: any) {
            return ctx.value;
          },
          align: 'center',
        },
        opposite: false,
        reversed: IsOrder,
        min: Number(dataList[0].MinData),
        max: Number(dataList[0].MaxData),
        tickWidth: 1,
        tickLength: 5,
        lineWidth: 1,
        lineColor: '#bfbfbf',
        tickColor: '#bfbfbf',
        offset: 0,
        visible: true,
        gridLineWidth: 0,
        tickPosition: 'inside',
        endOnTick: false,
        startOnTick: false,
        showLastLabel: true,
        tickPixelInterval: 50
      }

      //数据列
      let series: any = {
        data: [],
        type: 'scatter',
        name: language.value == 'ch'?`${chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`:`${chartInfo.ChartNameEn}${IsOrder ? '(reserve)' : ''}`,
        color: ChartColor,
        lineWidth: 0
      }
      real_data.forEach(_ => {
        series.data.push([_.x,_.y])
      })
      
      state.options = {
        title: {
          text:''
        },
        series: [ series ],
        yAxis,
        xAxis: {
          ...scatterXAxis,
          title: {
            text: language.value=='ch'?`${dataList[0].Unit}`:dataList[0].Unit?dataList[0].UnitEn:'',
            // text: null,
            align: 'high',
            rotation: 0,
            x: 0,
            offset: 20,
          },
        },
        tooltip
      }
      console.log(state.options)
    }


    /* 获取图表详情后赋值柱状图数据 */
    const initBarData = (data: { XEdbIdValue: number[]; YDataList: any; EdbInfoList: any; ChartInfo: any; }) => {
      const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data;

      state.barDateList = YDataList;
      state.barXIdData = XEdbIdValue;
      state.barEdbData = EdbInfoList;
      state.chartLimit = {
        min: Number(ChartInfo.LeftMin),
        max: Number(ChartInfo.LeftMax),
      }

      setBarChart();
    }
    /* 奇怪柱状图 和以上逻辑无公用点 依赖数据为单独的数据
      x轴为指标名称的柱形图 以日期作为series
    */
    const setBarChart = () => {
      const {barDateList,barXIdData,chartLimit,barEdbData,chartInfo} = state;
      let seriesData: { data: any; type: string; yAxis: number; name: any; color: any; chartType: string; }[] = [];
      const data = _.cloneDeep(barDateList);

      let categories = language.value==='ch' 
        ? barXIdData.map((_:number) => barEdbData.find((edb: { EdbInfoId: number; }) => edb.EdbInfoId===_).EdbAliasName)
        : barXIdData.map((_:number) => barEdbData.find((edb: { EdbInfoId: number; }) => edb.EdbInfoId===_).EdbNameEn)

      //x轴
      let xAxis = {
        ...scatterXAxis,
        categories,
        tickWidth: 1,
        title: {
          text:  ``,
          align: 'high',
          rotation: 0,
          x: 0,
          offset: 20,
        },
      }

      const { max,min } = chartLimit;
      console.log(max,min)
      //y轴
      let yAxis = {
        ...basicYAxis,
        title: {
          text:  language.value==='ch' ? chartInfo.Unit : chartInfo.UnitEn,
          align: 'high',
          rotation: 0,
          y: -15,
          offset: 0,
        },
        labels: {
          formatter: function (ctx:any) {
            let val = ctx.value;
            return val;
          },
          align: 'center',
        },
        min: Number(min),
        max: Number(max),
        opposite: false,
        tickWidth: 1,
      }

      //数据列
      data.forEach((item: { Value: number; Name: string; Date: string; Color: string; }) => {
        let serie_item = {
          data: item.Value,
          type: 'column',
          yAxis: 0,
          name: language.value==='ch' ? (item.Name || item.Date) : item.Date,
          color: item.Color,
          chartType: 'linear'
        };
        seriesData.push(serie_item)
      })
      
      state.options = {
        title: {
          text:''
        },
        plotOptions: {
          column:{
            stacking: null,
          },
        },
        series: seriesData,
        yAxis: [ yAxis ],
        xAxis
      }
    }

     /* 商品价格曲线获取详情赋值 */
    const initCommodityData = (data: { XDataList: any[]; YDataList: any; EdbInfoList: any; ChartInfo: any; DataResp?:any }) => {
      const { XDataList,YDataList,EdbInfoList,ChartInfo,DataResp } = data;

      state.commodityEdbList = EdbInfoList;
      state.commodityChartData = ChartInfo.Source===5?DataResp.YDataList:YDataList;
      state.commodityXData = ChartInfo.Source===5?DataResp.XDataList:XDataList;

      if(ChartInfo.Source===5) {
        state.chartInfo =  {
          ...state.chartInfo,
          ProfitName: DataResp.ProfitName,
          ProfitNameEn: DataResp.ProfitNameEn
        }
      }
      state.chartLimit = {
        min: Number(ChartInfo.LeftMin),
        max: Number(ChartInfo.LeftMax)
      }
      setCommodityChart();
    }
    /* 商品价格曲线设置 绘图逻辑同奇怪柱形图*/
    const setCommodityChart = () => {
      const {chartLimit,commodityChartData,commodityXData,commodityEdbList,chartInfo} = state;
      let seriesData:any[] = [];
      const data = _.cloneDeep(commodityChartData);
      //x轴
      let xAxis = {
        ...scatterXAxis,
        categories: commodityXData.map(_ => language.value === 'ch' ? _.Name:_.NameEn),
        tickWidth: 1,
        title: {
          text:  ``,
          align: 'high',
          rotation: 0,
          x: 0,
          offset: 20,
        },
      }

      const { max,min } = chartLimit;
      //y轴
      let yAxis = {
        ...basicYAxis,
        title: {
          text: language.value === 'ch' ? commodityEdbList[0].Unit : commodityEdbList[0].UnitEn,
          align: 'high',
          rotation: 0,
          y: -15,
          offset: 0,
        },
        labels: {
          formatter: function (ctx:any) {
            let val = ctx.value;
            return val;
          },
          align: 'center',
        },
        min: Number(min),
        max: Number(max),
        opposite: false,
        tickWidth: 1,
      }

      //数据列
      data.forEach((item: { Value: number[]; Name: string; Date: string; Color: string;NameEn: string,XEdbInfoIdList: number[],NoDataEdbList: number[] }) => {
        //处理首或/尾全是无效数据的以null填充
        let filterData = filterInvalidData(item)

        let serie_item = {
          data: filterData,
          type: 'spline',
          yAxis: 0,
          name: language.value === 'ch' ? item.Name : item.NameEn,
          color: item.Color,
          chartType: 'linear',
          lineWidth: 3,
          marker: {
            enabled: false
          }
        };
        seriesData.push(serie_item)
      })

      //tooltip
      let tooltip = {
        formatter: function() {
          const ctx: any = this;
          let str: string = '';

          if(language.value === 'ch') {
            
            ctx.points.forEach((item: { series:{name: string},y: number,color: string }) => {
              let obj_item = data.find((_:any) => _.Name === item.series.name);
              let index = commodityXData.findIndex(_ => _.Name === ctx.x);

              //合约显示
              let haveContract = obj_item.XEdbInfoIdList[index];
              if(haveContract) {
                // 利润曲线指标名
                let edb_name = chartInfo.Source === 5 
                  ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitName}(${obj_item.NameList[index]})`)
                  : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbName;
                str+=`<b>${ edb_name }</b>`
    
                if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) {
                  str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: ${item.y}<br>`
                }else {
                  str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: 无<br>`
                }
              }
            })
          }else {

            ctx.points.forEach((item: { series:{name: string},y: number,color: string }) => {
              let obj_item = data.find((_: any) => _.NameEn === item.series.name);
              let index = commodityXData.findIndex(_ => _.NameEn === ctx.x);

              let haveContract = obj_item.XEdbInfoIdList[index];
              if(haveContract) {

                let edb_name = chartInfo.Source === 5
                  ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitNameEn}(${obj_item.NameList[index]})`)
                  : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbNameEn;
                str+=`<b>${ edb_name }</b>`

                if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) {
                  str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: ${item.y}<br>`
                }else {
                  str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: 无<br>`
                  
                }
              }
            })
          }

          return str || '无合约'
        },
        shared: true
      }
      
      state.options = {
        title: {
          text:''
        },
        series: seriesData,
        yAxis: [ yAxis ],
        xAxis,
        tooltip
      }
    };
    /* 处理无效数据为null */
    const filterInvalidData = (item:{ Value: number[]; Name: string; Date: string; Color: string;NameEn: string,XEdbInfoIdList: number[],NoDataEdbList: number[] })=> {
      let validateArr = item.XEdbInfoIdList.filter(_ => _&&!item.NoDataEdbList.includes(_));

      let first_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[0]);
      let last_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[validateArr.length-1]);
      console.log('first_index',first_index)
      console.log('last_index',last_index)

      let arr = item.Value.map((item,index:number) => {
        if(index < first_index || index > last_index) {
          return null
        }else {
          return item
        }
      })

      return arr;
    }

    /* 设置options */
    const setOptions = () => {
      // ChartType: 1曲线图 2季节图 3面积图 4柱状图 5散点图 6组合图  季节图中公历和农历数据结构不同
      const { chartInfo } = state;
      const chartSetMap: any = {
        1: setDefaultLineOptions,
        2: setSeasonOptions,
        3: setStackOrCombinChart,
        4: setStackOrCombinChart,
        5: setScatterChartOptions,
        6: setStackOrCombinChart
      };

      chartSetMap[chartInfo.ChartType]()
    };

    /* 拼接动态的指标名称小标签 */
    const concatDynamicTag = ({ IsAxis,IsOrder,EdbInfoType,LeadValue,LeadUnit }: IDataProps,lang:String='ch'): string => {
      // IsAxis左轴1 右轴0 2右2轴 
      //IsOrder正序false 逆序true 
      //EdbInfoType是否是领先指标
      const axisLabelMap:any = lang=='ch'?{
        0: '右轴',
        2: '右2轴'
      }:{
        0: 'RHS',
        2: '2-RHS'
      }
      const orderLabelMap:any = lang=='ch'?{
        1: '逆序'
      }:{
        1: 'REV'
      }
      const edbInfoMap:any = lang=='ch'?{
        0: '领先'
      }:{
        0: 'Lead'
      }

      const leadUnitEnMap:any = {
        '年': 'Y',
        '季': 'Q',
        '月': 'M',
        '周': 'W',
        '天': 'D',
      }
      //英文领先单位转换
      const edbLeadUnit = lang=='ch' ? LeadUnit : leadUnitEnMap[LeadUnit];
      
      let axis_tag = axisLabelMap[IsAxis] || '';
      //逆序拼接
      let order_tag = orderLabelMap[Number(IsOrder)] ? `${axis_tag ? ',': ''}${orderLabelMap[Number(IsOrder)]}` : ''
      //领先拼接
      let edb_tag = edbInfoMap[EdbInfoType] ? `${(axis_tag||order_tag) ? ',' : '' }${edbInfoMap[EdbInfoType]} ${LeadValue}${edbLeadUnit}` : '';

      return (axis_tag || order_tag || edb_tag) ? `(${axis_tag}${order_tag}${edb_tag})` : ''
    }

     /* 预测配置 分区 */
    const getPredictParams = ({LatestDate,PredictChartColor,ChartStyle}: IDataProps,chartStyle='') => {
      return {
        zoneAxis: 'x',
        zones: [{
          value: new Date(LatestDate).getTime()+1
        }, {
          dashStyle: 'ShortDot',
          color:(ChartStyle==='column' || chartStyle==='column') ? 'transparent' : PredictChartColor
        }]
      }
    }
    
    /* 季节图预测数据 年份=分割点年份做分割 年份>分割点年份全为预测 */
    const getSeasonPredictParams = (timestamp: number) => {
      return timestamp
        ? {
            zoneAxis: 'x',
            zones: [{
              value: new Date(timestamp).getTime()+1
            }, {
              dashStyle: 'ShortDot',
            }]
          }
        : {}
    }

    /* 复制标题 */
    const copyText = () => {
      const { chartInfo } = state;
      let input = document.createElement("input");
      input.value = chartInfo.ChartName;
      document.body.appendChild(input)
      input.select();
      document.execCommand('copy');
      document.body.removeChild(input);
      ElMessage.success('复制标题成功')
    }

    /* 分享链接 */
    const copyUrl = () => {
      let input = document.createElement("input");
      input.value = location.href;
      document.body.appendChild(input)
      input.select();
      document.execCommand('copy');
      document.body.removeChild(input);
      ElMessage.success('复制链接成功')
    }

    const refreshChart = _.debounce(async () => {
      loading.value = true;
      let res: any=null
      if([1,6].includes(state.chartInfo.Source)){
        res=await ChartApi.refreshChart({UniqueCode: state.chartInfo.UniqueCode})
      }else if([2,5].includes(state.chartInfo.Source)){
        res=await ChartApi.refreshCommordityChart({UniqueCode: state.chartInfo.UniqueCode});
      }else if([3,4].includes(state.chartInfo.Source)){
        res=await ChartApi.refreshRelevanceChart({UniqueCode: state.chartInfo.UniqueCode});
      }
      loading.value = false;
      res.Ret === 200 && getChartInfo('refresh');
    },400)

    return {
      ...toRefs(state),
      loading,
      haveData,
      getChartInfo,
      openNew,
      copyUrl,
      isShare,
      language,
      refreshChart,
      copyText
    };
  },
});
</script>
<style scoped lang="less">
@import './index.less';
</style>
