import moment from 'moment';
import { computePrefixExpression } from './compute';

import {
  getDeviceRealData,
  getDeviceRealDataByTime,
  getDeviceRealData2,
  getExcelUrl,
  queryFormCurrentData,
  queryFormHistoryData,
  queryFormHistoryData2,
} from '@/services/ProjectAdmin';
export async function getOptions(values, datas, formula, projectId) {
  let plcDatas = [],
    formDatas = [];
  datas.forEach((item, index) => {
    item.index = index;
    if (item.data_type == 0) {
      plcDatas.push(item);
    } else {
      formDatas.push(item);
    }
  });

  var plcData = await getPlcOptions(values, plcDatas, formula, projectId);
  var formData = await getFormOptions(values, formDatas, projectId);

  if (values.timeType) {
    // 获得时间轴全集
    let times = getTimes(plcData[0]?.data, formData[0]?.data);

    // 根据时间全集补填数据
    formatData(plcData, times);
    formatData(formData, times);
  }
  // console.log(formData, plcData);
  return {
    ...values,
    // 合并data
    data: plcData.concat(formData),
  };
}

function getTimes(plcTimes = [], formTimes = []) {
  let times = {};

  plcTimes.forEach(item => {
    times[item.htime] = true;
  });
  formTimes.forEach(item => {
    times[item.htime] = true;
  });
  return Object.keys(times).sort((a, b) => new Date(a) - new Date(b));
}

// 根据时间进行格式化数据
function formatData(datas, times) {
  datas.forEach(item => {
    // 默认数据
    let newItemData = [];
    let i = 0;
    times.forEach(t => {
      let curData = item.data.find(item => item.htime == t);
      if (!curData) {
        // 空缺时间要补0
        newItemData.push({
          htime: t,
          val: 0,
        });
      } else {
        newItemData.push(curData);
      }
    });
    // 使用新值
    item.data = newItemData;
  });
}

/**
 * 获取图表的options
 * @param {object} values 表单数据
 * @param {array} datas 数据项
 * @param {array} formula 数据公式
 * @returns
 */
export async function getPlcOptions(values, datas, formula, project_id) {
  let arrtData = values.data || [];
  let params = getSingleData(datas, project_id);
  // let multiParams = getFormula(formula);
  if (!values.timeType) {
    let res = await getData(params, values);
    // for (let i = 0; i < multiParams.length; i++) {
    //   let device = multiParams[i].paramsDevice;
    //   let indexArr = multiParams[i].indexArr;
    //   let tempExpression = [...multiParams[i].expression];
    //   let formulaRes = await getData(device, values);
    //   formulaRes.data.map(res => {
    //     let temp = device.find(child => child.deviceName === res.alias);
    //     // console.log(temp);
    //     if (temp) {
    //       var indexObj = indexArr.find(item => item.deviceName === temp.deviceName);
    //       if (indexObj) {
    //         tempExpression[indexObj.index] = res.val;
    //       }
    //     }
    //   });
    //   let tempValue = computePrefixExpression([...tempExpression]);
    //   multiParams[i].formatExpression = tempExpression;
    //   multiParams[i].value = tempValue;
    // }
    let resData = res.data.map((item, index) => {
      let attrDataItem = arrtData[index + formula.length] || {};
      return {
        ...attrDataItem,
        name: item.alias,
        value: item.val * 1,
      };
    });
    // let formulaData = multiParams.map((item, index) => {
    //   let attrDataItem = arrtData[index] || {};
    //   return {
    //     ...attrDataItem,
    //     name: item.FormulaName,
    //     value: item.value * 1,
    //   };
    // });

    // return [...resData, ...formulaData];
    return resData;
  } else {
    let singleData = [];
    for (let i = 0; i < params.length; i++) {
      const item = params[i];
      let res = await getData(item, values);
      // let attrDataItem = arrtData[i + multiParams.length] || {};
      let attrDataItem = arrtData[i + formula.length] || {};
      singleData.push({
        ...attrDataItem,
        name: item.deviceName,
        data: (res.data || []).map(item => {
          return {
            val: item.val,
            htime: moment(item.htime_at).format('YYYY-MM-DD HH:mm:ss'),
          };
        }),
      });
    }

    // let firstHTimeArr = [];
    // let formulaData = [];
    // for (let i = 0; i < multiParams.length; i++) {
    //   const element = multiParams[i];
    //   let indexArr = element.indexArr;
    //   let tempExpression = [...element.expression];
    //   let device = element.paramsDevice;
    //   let child = {};
    //   child.tempExpression = tempExpression;
    //   child.name = element.FormulaName;
    //   child.data = [];
    //   child.indexArr = indexArr;
    //   for (let j = 0; j < device.length; j++) {
    //     const tempDevice = device[j];
    //     let res = await getData(tempDevice, values);
    //     child.data.push({
    //       data: res.data,
    //       device: tempDevice,
    //     });
    //   }
    //   formulaData.push(child);
    // }

    // let data = [];

    // formulaData.map((item, index) => {
    //   let attrDataItem = arrtData[index] || {};
    //   data.push({ ...attrDataItem, ...getFunctionValue(item) });
    // });

    // return [...singleData, ...data];
    return singleData;
  }
}
// 根据数据项获取请求参数
function getSingleData(datas, project_id) {
  let params = [];
  datas.forEach(({ device_id, device_items, seq }) => {
    if (device_id && device_items) {
      params.push({
        deviceName: seq,
        deviceId: device_id,
        deviceItems: device_items,
        project_id: Number(project_id),
      });
    }
  });
  return params;
}
// 根据公式获得请求参数
function getFormula(formula) {
  let params = [];
  formula.forEach(item => {
    let tempItem = item;
    let tempDeviceArr = [];
    let indexArr = [];
    item.params.map(item => {
      if (item.data_type == 1) {
      } else if (item.Id && item.ItemAlias && item.ItemName) {
        tempDeviceArr.push({
          deviceName: item.ItemAlias,
          deviceId: String(item.PlcDeviceId),
          deviceItems: item.ItemName,
        });

        indexArr.push({ index: item.index, deviceName: item.ItemAlias });
      }
    });
    tempItem.paramsDevice = tempDeviceArr;
    tempItem.indexArr = indexArr;
    params.push(tempItem);
  });
  return params;
}

function getFunctionValue(child) {
  let data = {};
  data.data = [];
  let expression = child.tempExpression;
  let first = child.data[0];
  let indexArr = child.indexArr;
  first.data.forEach(item => {
    // firstDevice.device
    let resObj = {
      [first.device.deviceName]: item,
    };
    let htime = item.htime;
    for (let i = 1; i < child.data.length; i++) {
      let element = child.data[i];
      // deviceName = element.name
      let result = element.data.find(item => item.htime === htime);
      if (!result) return;
      resObj[element.device.deviceName] = result;
    }
    Object.keys(resObj).forEach(key => {
      var result = indexArr.find(item => key === item.deviceName);
      if (result) expression[result.index] = resObj[key].val;
    });
    // console.log(expression);
    data.data.push({
      htime: moment(htime).format('YYYY-MM-DD HH:mm:ss'),
      val: computePrefixExpression([...expression]),
    });
    // console.log(indexArr, resObj, expression);
    //  indexArr   resObj     expression
  });
  data.name = child.name;
  return data;
}

var DATA_CACHE = {};
// 请求plc数据
async function getData(params, values) {
  const { timeType, date, size, interval, aggregator } = values;
  let key, etime, stime;
  if (!timeType) {
    // key = `${params.map(item => item.deviceItems).join(',')}-${timeType}`;
  } else if (timeType != -1) {
    // key = `${params.deviceItems}-${timeType}-${size}-${interval}-${aggregator}`;
  } else {
    let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 };
    etime = moment(date[1]).set(clear) * 1;
    stime = moment(date[0]).set(clear) * 1;
    // key = `${params.deviceItems}-${stime}-${etime}-${size}-${interval}-${aggregator}`;
  }
  // if (!DATA_CACHE[key]) {
  if (!timeType) {
    // DATA_CACHE[key] = await getDeviceRealData(params);
    return await getDeviceRealData(params);
  } else {
    if (timeType != -1) {
      let currentDate = moment();
      etime = currentDate * 1;
      stime = currentDate.add(-1 * timeType, 'hour') * 1;
    }
    return await getDeviceRealDataByTime({
      deviceid: params.deviceId * 1,
      dataitemid: params.deviceItems,
      project_id: Number(params.project_id),
      stime,
      etime,
      size,
      interval,
      aggregator,
    });
  }
  // }
  // return DATA_CACHE[key];
}

// 请求plc历史数据
async function getDataHistory(params, values) {
  const { timeType, size, interval, aggregator, date } = values;
  let currentDate = moment();
  let etime;
  let stime;
  let res = [];
  if (timeType != -1) {
    let currentDate = moment();
    etime = currentDate * 1;
    stime = currentDate.add(-1 * timeType, 'hour') * 1;
  } else {
    let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 };
    etime = moment(date[1]).set(clear) * 1;
    stime = moment(date[0]).set(clear) * 1;
  }
  for (var i = 0; i < params.length; i++) {
    const item = params[i];
    const { data } = await getDeviceRealDataByTime({
      deviceid: item.deviceId * 1,
      dataitemid: item.deviceItems,
      project_id: Number(item.project_id),
      stime,
      etime,
      size,
      interval,
      aggregator,
    });
    res.push({
      paramsInfo: item,
      name: item.deviceName,
      data: (data || [])
        .filter(item => item.htime_at)
        .map(item => {
          return {
            val: item.val * 1,
            htime: moment(item.htime_at).format('YYYY-MM-DD HH:mm:ss'),
          };
        }),
    });
  }
  return res;
}

// 获取表单的options
export async function getFormOptions(values, datas, projectId) {
  let arrtData = values.data || [];
  const params = getFormParams(datas, projectId);
  if (!values.timeType) {
    // 请求最新数据
    let data = await getFormCurrentData(params, values);
    let resData = data.map((item, index) => {
      let attrDataItem = arrtData[index] || {};
      return {
        ...attrDataItem,
        name: item.title,
        value: item.value * 1,
      };
    });
    return resData;
  } else {
    // 请求历史数据
    let data = await getFormHistoryData(params, values);
    return data.map((item, i) => {
      let attrDataItem = arrtData[i] || {};
      return {
        ...attrDataItem,
        ...item,
      };
    });
  }
}

// 根据表单的数据项获取请求参数
function getFormParams(datas, projectId) {
  let params = {};
  datas.forEach(item => {
    if (!params[item.data_name]) params[item.data_name] = [];
    params[item.data_name].push(item.data_title);
  });
  return Object.keys(params).map(data_name => ({
    formName: data_name,
    titles: params[data_name],
    projectId,
  }));
}

// 请求表单最新数据
async function getFormCurrentData(params, values) {
  const { timeType, date } = values;
  let data = [];
  for (let i = 0; i < params.length; i++) {
    const resData = await queryFormCurrentData(params[i]);
    data = [...data, ...resData];
  }
  return data;
}

// 请求表单历史数据
async function getFormHistoryData(params, values) {
  const { timeType, date, size, interval, aggregator } = values;
  let sTime, eTime;
  let data = [];
  // -1为自选日期  从date内获取时间
  if (timeType == -1) {
    let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 };
    eTime = moment(date[1])
      .set(clear)
      .format('YYYY-MM-DD HH:mm');
    sTime = moment(date[0])
      .set(clear)
      .format('YYYY-MM-DD HH:mm');
  } else {
    let currentDate = moment();
    eTime = currentDate.format('YYYY-MM-DD HH:mm');
    sTime = currentDate.add(-1 * timeType, 'hour').format('YYYY-MM-DD HH:mm');
  }

  // for (let i = 0; i < params.length; i++) {
  //   const resData = await queryFormHistoryData({ ...params[i], eTime, sTime });
  //   data = [...data, ...resData];
  // }
  const item_info = params.map(item => ({
    table: item.formName,
    pro: item.titles.map(title => ({ key: title })),
  }));
  let queryParams = {
    project_id: Number(params[0].projectId),
    item_info,
    stime: sTime,
    etime: eTime,
    interval,
    size: Number(size),
    aggregator,
  };
  const resData = await queryFormHistoryData2(queryParams);

  return resData;
}

async function queryData(values, datas, projectId) {
  let plcDatas = [],
    formDatas = [];
  datas.forEach(item => {
    if (item.data_type == 0) {
      plcDatas.push(item);
    } else {
      formDatas.push(item);
    }
  });

  // 根据params获取form的数据
  var formData = await getFormData(values, formDatas, projectId);
  var plcData = await getPlcData(values, plcDatas, projectId);
  if (values.timeType) {
    // 获得时间轴全集
    let times = getTimes(plcData[0]?.data, formData[0]?.data);

    // 根据时间全集补填数据
    formatData(plcData, times);
    formatData(formData, times);
  }
  return {
    plcData,
    formData,
  };
}

async function getFormData(values, datas, projectId) {
  let arrtData = values.data || [];
  const params = getFormParams(datas, projectId);
  if (params.length == 0) return [];
  if (!values.timeType) {
    // 请求最新数据
    return await getFormCurrentData(params, values);
  } else {
    // 请求历史数据
    return await getFormHistoryData(params, values);
  }
}
async function getPlcData(values, datas, project_id) {
  let arrtData = values.data || [];
  let params = getSingleData(datas, project_id);
  if (!values.timeType) {
    let res = await getData(params, values);
    return res.data;
  } else {
    // let singleData = [];
    // for (let i = 0; i < params.length; i++) {
    //   const item = params[i];
    //   let res = await getData(item, values);
    //   singleData.push({
    //     paramsInfo: item,
    //     name: item.deviceName,
    //     data: (res.data || [])
    //       .filter(item => item.htime_at)
    //       .map(item => {
    //         return {
    //           val: item.val * 1,
    //           htime: moment(item.htime_at).format('YYYY-MM-DD HH:mm:ss'),
    //         };
    //       }),
    //   });
    // }
    // return singleData;
    return await getDataHistory(params, values);
  }
}

export async function getOptions2(values, datas, formula, projectId) {
  let allDatas = getAllParams(datas, formula);
  if (allDatas.length == 0) return;

  let optionsData = getOptionsData(datas, formula, values);

  // 请求接口
  const { plcData, formData } = await queryData(values, allDatas, projectId);

  optionsData = optionsData.map(item => {
    const paramsInfo = item.paramsInfo;
    let res;
    if (paramsInfo.data_type == 0) {
      // plc数据
      res = findPlcData(paramsInfo, plcData, values.timeType);
    } else if (paramsInfo.data_type == 1) {
      // form数据
      res = findFormData(paramsInfo, formData, values.timeType);
    } else if (paramsInfo.data_type == 2) {
      // 获取公式的值
      res = getFormulaData(item.paramsInfo, plcData, formData, values.timeType);
    }
    return { ...item, ...res };
  });
  return {
    ...values,
    data: optionsData,
  };
}

function findPlcData(paramsInfo, plcData, timeType) {
  // 实时数据与历史数据结构不一致  需判断
  if (timeType) {
    return plcData.find(resItem => resItem.paramsInfo.deviceName == paramsInfo.seq);
  } else {
    let res = plcData.find(
      resItem =>
        resItem.itemname == paramsInfo.device_items && resItem.devid == paramsInfo.device_id
    );
    return {
      name: res.alias,
      value: res.val,
    };
  }
}
function findFormData(paramsInfo, formData, timeType) {
  // 实时数据与历史数据结构不一致  需判断
  if (timeType) {
    return formData.find(resItem => resItem.name == paramsInfo.data_title);
  } else {
    let res = formData.find(resItem => resItem.title == paramsInfo.data_title);
    return {
      name: res.title,
      value: res.value,
    };
  }
}

function getAllParams(datas, formula) {
  let allDatas = [...datas];
  formula.forEach(f => {
    f.params.forEach(params => {
      if (params.data_type == 0) {
        if (!datas.find(item => item.seq == params.seq)) {
          allDatas.push(params);
        }
      } else {
        if (!datas.find(item => item.data_title == params.data_title)) {
          allDatas.push(params);
        }
      }
    });
  });
  return allDatas;
}

function getOptionsData(datas, formula, values) {
  let valuesData = values.data || [];

  let optionsData = [];
  formula.forEach((item, index) => {
    var arrData = valuesData[index] || {};
    item.data_type = 2;
    arrData.paramsInfo = item;
    optionsData.push(arrData);
  });
  datas.forEach((data, index) => {
    var arrData = valuesData[index + formula.length] || {};
    arrData.paramsInfo = data;
    optionsData.push(arrData);
  });
  return optionsData;
}

function getFormulaData(formula, plcData, formData, timeType) {
  let expression = [...formula.expression];
  let resDatas = formula.params.map(params => {
    let res;
    if (params.data_type == 0) {
      res = findPlcData(params, plcData, timeType);
      return {
        ...params,
        ...res,
      };
    } else {
      res = findFormData(params, formData, timeType);
      return {
        ...params,
        ...res,
      };
    }
  });

  if (timeType) {
    let optionsData = [];
    // 获取时间
    let time = resDatas[0].data.map(item => item.htime);
    time.forEach((htime, index) => {
      resDatas.forEach(params => {
        // 根据index去替换表达式中对应的值
        expression[params.index] = params.data[index].val || 0;
      });
      optionsData.push({
        htime: moment(htime).format('YYYY-MM-DD HH:mm:ss'),
        val: computePrefixExpression([...expression]),
      });
    });
    return {
      data: optionsData,
      name: formula.FormulaName,
    };
  } else {
    resDatas.forEach(params => {
      // 根据index去替换表达式中对应的值
      expression[params.index] = params.value || 0;
    });
    return {
      value: computePrefixExpression([...expression]),
      name: formula.FormulaName,
    };
  }
}
