class getIrisDataDispose {
  spectralName;
  irisData;
  spectralInfoData;
  spectral_data;
  image_info;
  devinfoData;
  environmentData;

  constructor(irisData, spectralName, useDarkDn = true) {
    this.irisData = irisData;
    this.spectralName = spectralName;
    this.spectral_data = irisData.spectral_data_section;
    this.image_info = irisData.image_info_section;
    this.useDarkDn = useDarkDn;

    for (const element of irisData.spectral_info_section) {
      if (element.info_type == "devinfo") {
        this.devinfoData = element;
      } else if (element.info_type == "environment") {
        this.environmentData = element;
      }
    }
  }

  initData() {
    const basicTypes = ["ground_dn", "flat_dn", "dark_dn", "gain"];
    const specialTypes = [
      "flat_ref",
      "radiance_ground",
      "radiance_flat",
      "refrad",
    ];

    if (basicTypes.includes(this.spectralName)) {
      return this.getFileSpectralData();
    } else if (specialTypes.includes(this.spectralName)) {
      return this.getSpecialFileSpectralData();
    }
  }

  //获取一般后端直接返回的类型
  getFileSpectralData() {
    // 基础类型适配暗噪开关：ground_dn / flat_dn 在启用暗噪时做 “- dark_dn”
    const nameLower = (this.spectralName || '').toLowerCase();
    const bands = this.devinfoData?.bandnum ?? 0;
    const needDarkCorr =
      this.useDarkDn && (nameLower === 'ground_dn' || nameLower === 'flat_dn');

    if (needDarkCorr) {
      let mainEl = null; // ground_dn 或 flat_dn 的原始 element
      let darkEl = null; // dark_dn 的原始 element

      for (const element of this.spectral_data) {
        const lower = (element.name || '').toLowerCase();
        if (!mainEl && lower.includes(nameLower)) {
          mainEl = element;
        } else if (!darkEl && lower.includes('dark_dn')) {
          darkEl = element;
        }
        if (mainEl && darkEl) break;
      }

      if (!mainEl) {
        console.error(`未找到 ${nameLower} 数据，无法计算`);
        return undefined;
      }

      const mainTyped = manageSpectralData(mainEl, this.devinfoData);
      const main = Array.isArray(mainTyped) ? mainTyped : Array.from(mainTyped || []);
      const darkTyped = darkEl ? manageSpectralData(darkEl, this.devinfoData) : null;
      const dark = darkTyped ? (Array.isArray(darkTyped) ? darkTyped : Array.from(darkTyped)) : null;

      const corrected = [];
      const invalidCount = { missing: 0, invalidResult: 0 };

      for (let i = 0; i < bands; i++) {
        const mv = main[i];
        const dv = dark ? (dark[i] ?? 0) : 0;

        if (mv === undefined) {
          corrected.push(0);
          invalidCount.missing++;
          continue;
        }

        const v = mv - dv;
        if (Number.isFinite(v) && !Number.isNaN(v)) {
          corrected.push(v);
        } else {
          corrected.push(0);
          invalidCount.invalidResult++;
        }
      }

      if (!dark) {
        console.warn(`${nameLower} 去暗噪: 未找到 dark_dn，按 0 处理`);
      } else if (dark.length !== bands) {
        console.warn(
          `${nameLower} 去暗噪: dark_dn 长度(${dark.length})与波段数(${bands})不一致，按可用索引减，缺失部分按 0`
        );
      }
      if (invalidCount.missing > 0 || invalidCount.invalidResult > 0) {
        console.warn(
          `${nameLower} 去暗噪: 缺失值 ${invalidCount.missing} 个，无效结果 ${invalidCount.invalidResult} 个，有效数据 ${corrected.length} 个`
        );
      }

      return { ...mainEl, normalArray: corrected };
    }

    // 默认路径：保持原逻辑（未启用暗噪或其它基础类型）
    for (const element of this.spectral_data) {
      const typedArray = manageSpectralData(element, this.devinfoData);
      const normalArray = Array.from(typedArray);
      if ((element.name || '').toLowerCase().includes(nameLower)) {
        return { ...element, normalArray };
      }
    }
  }

  //获取需要计算的类型
  getSpecialFileSpectralData() {
    let spectralDataMap = new Map([
      ["ground_dn", null],
      ["flat_dn", null],
      ["dark_dn", null],
      ["flat_ref", null],
      ["gain", null],
      ["radiance_ground", null],
      ["radiance_flat", null],
      ["refrad", null],
    ]);
    for (const element of this.spectral_data) {
      const typedArray = manageSpectralData(element, this.devinfoData);
      const normalArray = Array.from(typedArray);
      if (element.name.toLowerCase().includes("ground_dn")) {
        spectralDataMap.set("ground_dn", { ...element, normalArray });
      } else if (element.name.toLowerCase().includes("flat_dn")) {
        spectralDataMap.set("flat_dn", { ...element, normalArray });
      } else if (element.name.toLowerCase().includes("dark_dn")) {
        spectralDataMap.set("dark_dn", { ...element, normalArray });
      } else if (element.name.toLowerCase().includes("gain")) {
        spectralDataMap.set("gain", { ...element, normalArray });
      }
    }
  
    // 分支依赖校验与辅助函数
    const has = (key) => !!spectralDataMap.get(key);
    const requireDeps = (deps) => deps.every((k) => has(k));
    const buildArrAll = (keys) => {
      const obj = {};
      for (const k of keys) obj[k] = spectralDataMap.get(k).normalArray;
      return mergeObjectArrays(obj);
    };
    const baseName = (...preferredKeys) => {
      for (const k of preferredKeys) {
        if (has(k)) return spectralDataMap.get(k).name.split("_")[0];
      }
      return "unknown";
    };
  
    // 结果验证（依赖不够时不会走到这里）
    const validateResult = (array, name, type) => {
      if (array.length === 0) {
        console.error(`${type}计算错误: 没有有效的数据点，无法生成图表`);
        return { normalArray: [], name: name };
      }
      return { normalArray: array, name: name };
    };
  
    if (this.spectralName == "radiance_ground") {
      const deps = ["gain", "ground_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
      if (!requireDeps(deps)) return undefined; // 依赖不够，直接返回空，保持原逻辑
      const arrAll = buildArrAll(deps);
      const name = baseName("ground_dn", "gain");
  
      const radiance_ground = [];
      const invalidCount = { zeroDiv: 0, invalidResult: 0 };
  
      for (const element of arrAll) {
        const gainExposure = spectralDataMap.get("gain").exposure;
        const groundExposure = spectralDataMap.get("ground_dn").exposure;
  
        if (Math.abs(groundExposure) < 1e-10) {
          invalidCount.zeroDiv++;
          radiance_ground.push(0);
          continue;
        }
  
        const exposureRatio = gainExposure / groundExposure;
        const dnDiff = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
        const a = exposureRatio * (element.gain * dnDiff);
  
        if (isFinite(a) && !isNaN(a)) {
          radiance_ground.push(a);
        } else {
          invalidCount.invalidResult++;
          radiance_ground.push(0);
        }
      }
      if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
        console.warn(`radiance_ground计算统计: 除零错误 ${invalidCount.zeroDiv} 个，无效结果 ${invalidCount.invalidResult} 个，有效数据 ${radiance_ground.length} 个`);
      }
      return validateResult(radiance_ground, name + "_radiance_ground", "radiance_ground");
  
    } else if (this.spectralName == "radiance_flat") {
      const deps = ["gain", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
      if (!requireDeps(deps)) return undefined; // 依赖不够，直接返回空
      const arrAll = buildArrAll(deps);
      const name = baseName("flat_dn", "gain");
  
      const radiance_flat = [];
      const invalidCount = { zeroDiv: 0, invalidResult: 0 };
  
      for (const element of arrAll) {
        const gainExposure = spectralDataMap.get("gain").exposure;
        const flatExposure = spectralDataMap.get("flat_dn").exposure;
  
        if (Math.abs(flatExposure) < 1e-10) {
          invalidCount.zeroDiv++;
          radiance_flat.push(0);
          continue;
        }
  
        const exposureRatio = gainExposure / flatExposure;
        const dnDiff = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
        const b = exposureRatio * (element.gain * dnDiff);
  
        if (isFinite(b) && !isNaN(b)) {
          radiance_flat.push(b);
        } else {
          invalidCount.invalidResult++;
          radiance_flat.push(0);
        }
      }
      if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
        console.warn(`radiance_flat计算统计: 除零错误 ${invalidCount.zeroDiv} 个，无效结果 ${invalidCount.invalidResult} 个，有效数据 ${radiance_flat.length} 个`);
      }
      return validateResult(radiance_flat, name + "_radiance_flat", "radiance_flat");
  
    } else if (this.spectralName == "refrad") {
      const deps = ["gain", "ground_dn", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
      if (!requireDeps(deps)) return undefined; // 依赖不够，直接返回空
      const arrAll = buildArrAll(deps);
      const name = baseName("ground_dn", "flat_dn", "gain");
  
      const refrad = [];
      const invalidCount = { zeroDiv: 0, invalidResult: 0 };
  
      for (const element of arrAll) {
        const gainExposure = spectralDataMap.get("gain").exposure;
        const groundExposure = spectralDataMap.get("ground_dn").exposure;
        const flatExposure = spectralDataMap.get("flat_dn").exposure;
  
        if (Math.abs(groundExposure) < 1e-10 || Math.abs(flatExposure) < 1e-10) {
          invalidCount.zeroDiv++;
          refrad.push(0);
          continue;
        }
  
        const groundRatio = gainExposure / groundExposure;
        const flatRatio = gainExposure / flatExposure;
  
        const groundDnDiff = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
        const flatDnDiff = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
  
        const a = groundRatio * (element.gain * groundDnDiff);
        const b = flatRatio * (element.gain * flatDnDiff);
  
        if (Math.abs(b) < 1e-10) {
          invalidCount.zeroDiv++;
          refrad.push(0);
        } else {
          const c = a / b;
          if (isFinite(c) && !isNaN(c)) {
            refrad.push(c);
          } else {
            invalidCount.invalidResult++;
            refrad.push(0);
          }
        }
      }
      if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
        console.warn(`refrad计算统计: 除零错误 ${invalidCount.zeroDiv} 个，无效结果 ${invalidCount.invalidResult} 个，有效数据 ${refrad.length} 个`);
      }
      return validateResult(refrad, name + "_refrad", "refrad");
  
    } else if (this.spectralName == "flat_ref") {
      const deps = ["ground_dn", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
      if (!requireDeps(deps)) return undefined; // 依赖不够，直接返回空
      const arrAll = buildArrAll(deps);
      const name = baseName("ground_dn", "flat_dn");
  
      const validData = [];
      const invalidCount = { zeroDiv: 0, invalidResult: 0 };
  
      for (const element of arrAll) {
        const denominator = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
        const numerator = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
  
        if (Math.abs(denominator) < 1e-10) {
          invalidCount.zeroDiv++;
          validData.push(0);
        } else {
          const b = numerator / denominator;
          if (isFinite(b) && !isNaN(b)) {
            validData.push(b);
          } else {
            invalidCount.invalidResult++;
            validData.push(0);
          }
        }
      }
      if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
        console.warn(`flat_ref计算统计: 除零错误 ${invalidCount.zeroDiv} 个，无效结果 ${invalidCount.invalidResult} 个，有效数据 ${validData.length} 个`);
      }
      return validateResult(validData, name + "_flat_ref", "flat_ref");
    }
  }

  getSpectralInfoData() {
    let spectralInfoData = [];
    for (let i = 0; i < this.devinfoData.bandnum; i++) {
      const a =
        this.devinfoData.wave_coeff.a1 * i ** 3 +
        this.devinfoData.wave_coeff.a2 * i * i +
        this.devinfoData.wave_coeff.a3 * i +
        this.devinfoData.wave_coeff.a4;
      spectralInfoData.push(a);
    }
    return spectralInfoData;
  }

  parseImageData(image_info) {
    if (!image_info || image_info.length === 0) {
      console.log("No image data found");
      return [];
    }
    const imageInfos = image_info;
    const images = [];
    for (const imageInfo of imageInfos) {
      // 获取图像类型
      const imageType = imageInfo.info_type;
      let mimeType;
      switch (imageType) {
        case 0:
          mimeType = "image/jpeg";
          break;
        case 1:
          mimeType = "image/png";
          break;
        case 2:
          mimeType = "image/tiff";
          break;
        case 3:
          mimeType = "application/octet-stream"; // 原始数据
          break;
        default:
          mimeType = "application/octet-stream";
      }
      // 创建Blob对象
      const imageBlob = new Blob([new Uint8Array(imageInfo.image_data)], {
        type: mimeType,
      });
      // 创建URL
      const imageUrl = URL.createObjectURL(imageBlob);
      images.push({
        name: imageInfo.name,
        type: imageType,
        url: imageUrl,
        time: imageInfo.collection_time,
      });
    }

    return images;
  }
}

function mergeObjectArrays(obj) {
  const keys = Object.keys(obj);
  const length = obj[keys[0]].length;

  const result = [];

  for (let i = 0; i < length; i++) {
    const item = {};
    for (const key of keys) {
      item[key] = obj[key][i];
    }
    result.push(item);
  }

  return result;
}

const manageSpectralData = (rawData, devinfoData) => {
  const bands = devinfoData.bandnum;
  const uint8Array = new Uint8Array(rawData.spectral_data);
  try {
    switch (rawData.data_type) {
      case 0x20: // float32
        return new Float32Array(uint8Array.buffer, 0, bands);
      case 0x21: // float64
        return new Float64Array(uint8Array.buffer, 0, bands);
      case 0x10: // uint8
        return new Uint8Array(uint8Array.buffer, 0, bands);
      case 0x11: // int16
        return new Int16Array(uint8Array.buffer, 0, bands);
      case 0x12: // uint16
        return new Uint16Array(uint8Array.buffer, 0, bands);
      case 0x13: // int32
        return new Int32Array(uint8Array.buffer, 0, bands);
      case 0x14: // uint32
        return new Uint32Array(uint8Array.buffer, 0, bands);
      default:
        throw new Error(`Unsupported data type: 0x${dataType.toString(16)}`);
    }
  } catch (e) {
    error.value = `Failed to parse spectral data: ${e.message}`;
    return null;
  }
};

const spectralTypeList = [
  {
    value: "ground_dn",
    label: "地物DN",
  },
  {
    value: "flat_dn",
    label: "参考DN",
  },
  {
    value: "dark_dn",
    label: "暗噪DN",
  },
  {
    value: "flat_ref",
    label: "反射率",
  },
  {
    value: "gain",
    label: "能量校准文件",
  },
  {
    value: "radiance_ground",
    label: "地物辐射亮度",
  },
  {
    value: "radiance_flat",
    label: "参考辐射亮度",
  },
  // {
  //   value: "refrad",
  //   label: "反射率能量",
  // },
  // {
  //   value: "jdfs",
  //   label: "绝对反射率",
  // },
  // {
  //   value: "ckbzwj",
  //   label: "参考校准文件",
  // },
  // {
  //   value: "fszd",
  //   label: "辐射照度",
  // },
];

const spectralProcessTypeList = [
  {
    value: "D1",
    label: "一阶导数",
  },
  {
    value: "D2",
    label: "二阶导数",
  },
  {
    value: "MA",
    label: "移动平均平滑",
  },
];

function D1(arr) {
  const result = [];
  for (let i = 1; i < arr.length; i++) {
    result.push(arr[i] - arr[i - 1]);
  }
  result.push(arr[arr.length - 1]);
  return result;
}

function D2(arr) {
  const arr2 = D1(arr);
  return D1(arr2);
}

export {
  spectralTypeList,
  getIrisDataDispose,
  spectralProcessTypeList,
  D1,
  D2,
};
