import * as d3 from "d3-scale";
import { formatDefaultLocale } from "d3-format";
import "@kitware/vtk.js/Rendering/Profiles/Geometry";
import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";

import { throttle } from '@kitware/vtk.js/macros';
import {
  FieldDataTypes,
  FieldAssociations,
} from '@kitware/vtk.js/Common/DataModel/DataSet/Constants';


import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
import vtkLineSource from '@kitware/vtk.js/Filters/Sources/LineSource';
import vtkSphereMapper from '@kitware/vtk.js/Rendering/Core/SphereMapper';

export class VtkModel {
  constructor() {

    //当前显示 模版 还是结果
    this.isJg = false;

    /**
     * 选择点线 
     */
    this.isSelectNode = false;
    /**
     * 选择管道 
     */
    this.isSelectPipe = false;
    //管道节点选择对象
    this.selectObj = null;
    //结果选择的点数据
    this.selectJgPointId=0;
    this.validNodes = [];//节点数据
    this.pipes = [];//管道数据

    this.renderWindowWith = vtkFullScreenRenderWindow.newInstance();
    this.renderer = this.renderWindowWith.getRenderer();
    this.renderWindow = this.renderWindowWith.getRenderWindow();

    //模板数据
    this.polyData = vtkPolyData.newInstance();
    this.mapper = vtkMapper.newInstance();
    this.actor = vtkActor.newInstance();
    this.actor.getProperty().setRepresentation(Representation.SURFACE); //线    
    this.actor.getProperty().setColor(WHITE);
    this.mapper.setInputData(this.polyData);
    this.actor.setMapper(this.mapper);

    //点数据
    this.actor2 = vtkActor.newInstance();
    this.actor2.getProperty().setRepresentation(Representation.POINTS); //点   
    this.actor2.getProperty().setColor(WHITE);
    this.actor2.getProperty().setPointSize(2);
    this.actor2.setMapper(this.mapper);



    //选取
    this.lastActor = null;
    this.nodeActors = []; //节点actor 数据
    this.pipeActors = []; //管道actor 数据
    this.interactor = this.renderer.getRenderWindow().getInteractor();
    this.apiSpecificRenderWindow = this.interactor.getView();
    this.hardwareSelector = this.apiSpecificRenderWindow.getSelector();
    this.hardwareSelector.setCaptureZValues(true);
    this.hardwareSelector.setFieldAssociation(FieldAssociations.FIELD_ASSOCIATION_POINTS);
    document.addEventListener("mousemove", throttleMouseHandler);

    //结果数据
    this.jgActor = vtkActor.newInstance();
    this.jgMapper = vtkMapper.newInstance();
    this.jgActor.getProperty().setRepresentation(Representation.SURFACE); //面    


    this.scalarBarActor = vtkScalarBarActor.newInstance();
    this.scalarBarActor.setGenerateTicks(this.generateTicks(5));
    this.scalarBarActor.setDrawAboveRangeSwatch(true);
    this.scalarBarActor.setDrawNanAnnotation(false);
    this.scalarBarActor.setBoxPosition([1, 0]);
    // 修改设条颜色
    const ctf = vtkColorTransferFunction.newInstance();
    ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
    ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
    ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
    ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
    ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
    this.jgMapper.setLookupTable(ctf);
    const lut = this.jgMapper.getLookupTable();
    this.scalarBarActor.setScalarsToColors(lut);
    this.jgActor.setMapper(this.jgMapper);


  }
  generateTicks(numberOfTicks) {
    return (helper) => {
      const lastTickBounds = helper.getLastTickBounds();
      // compute tick marks for axes
      const scale = d3
        .scaleLinear()
        .domain([0.0, 1.0])
        .range([lastTickBounds[0], lastTickBounds[1]]);
      const samples = scale.ticks(numberOfTicks);
      const ticks = samples.map((tick) => scale(tick));
      // Replace minus "\u2212" with hyphen-minus "\u002D" so that parseFloat() works
      formatDefaultLocale({ minus: "\u002D" });
      const format = scale.tickFormat(ticks[0], ticks[ticks.length - 1], numberOfTicks);
      const tickStrings = ticks
        .map(format)
        .map((tick) => Number(parseFloat(tick).toPrecision(12)).toPrecision()); // d3 sometimes adds unwanted whitespace
      helper.setTicks(ticks);
      helper.setTickStrings(tickStrings);
    };
  }

  modelInit(validNodes, pipes) {
    this.validNodes = validNodes;
    this.pipes = pipes;
    this.modelCreate();
  }
  modelCreate() {
    console.log("modelInit..");
    const points = this.polyData.getPoints();
    const lines = this.polyData.getLines();

    //无节点actor
    this.validNodes.forEach((node) => {
      points.insertNextPoint(parseFloat(node.x), parseFloat(node.y), parseFloat(node.z));
    });
    //无管道actor
    this.pipes.forEach((pipe) => {
      let sid = this.indexIdByPipeNodeId(pipe.snId);
      let eid = this.indexIdByPipeNodeId(pipe.enId);
      lines.insertNextCell([sid, eid]);
    });

    //有节点actors
    const sphereSource = vtkSphereSource.newInstance({
      center: [0, 0, 0],
      radius: 4.0,
    });
    const mapper = vtkMapper.newInstance();
    mapper.setInputConnection(sphereSource.getOutputPort());
    this.validNodes.forEach((node) => {
      const actor = vtkActor.newInstance();
      actor.setMapper(mapper);
      actor.setPosition(parseFloat(node.x), parseFloat(node.y), parseFloat(node.z));
      actor.getProperty().setColor(WHITE);
      const nodeActor = {};
      nodeActor.node = node;
      nodeActor.actor = actor;
      this.nodeActors.push(nodeActor);
    });

    //有管道actors
    this.pipes.forEach((pipe) => {
      const lineSource = vtkLineSource.newInstance();
      let point1 = this.pointByPipeNodeId(pipe.snId);
      let point2 = this.pointByPipeNodeId(pipe.enId);
      lineSource.setPoint1(point1);
      lineSource.setPoint2(point2);
      lineSource.setResolution(12);
      const actor = vtkActor.newInstance();
      const mapper = vtkMapper.newInstance();
      actor.setMapper(mapper);
      actor.getProperty().setLineWidth(3);//设置线宽
      actor.getProperty().setColor(WHITE);
      mapper.setInputConnection(lineSource.getOutputPort());
      const pipeActor = {};
      pipeActor.pipe = pipe;
      pipeActor.actor = actor;
      this.pipeActors.push(pipeActor);
    });

    this.modelShow();
    this.renderer.resetCamera();
    this.renderWindow.render();
  }

  modelClearShow() {
    this.renderer.removeActor(this.actor);
    this.renderer.removeActor(this.actor2);
    this.nodeActors.forEach((nodeActor) => {
      this.renderer.removeActor(nodeActor.actor);
    });
    this.pipeActors.forEach((pipeActor) => {
      this.renderer.removeActor(pipeActor.actor);
    });
  }
  modelShow() {
    this.modelClearShow();
    if (!this.isSelectNode) {//不选择节点
      this.renderer.addActor(this.actor2);
    }
    if (!this.isSelectPipe) {//不选择管道
      this.renderer.addActor(this.actor);
    }
    if (this.isSelectNode) {//选择节点
      this.nodeActors.forEach((nodeActor) => {
        this.renderer.addActor(nodeActor.actor);
      });
    }
    if (this.isSelectPipe) {//选择管道
      this.pipeActors.forEach((pipeActor) => {
        this.renderer.addActor(pipeActor.actor);
      });
    }
  }
  selectNodes() {
    this.isSelectNode = true;
    this.isSelectPipe = false;
    this.modelShow();
    this.renderWindow.render();
  }
  selectPipes() {
    this.isSelectNode = false;
    this.isSelectPipe = true;
    this.modelShow();
    this.renderWindow.render();
  }
  selectNoting(){
    this.isSelectNode = false;
    this.isSelectPipe = false;
    this.modelShow();
    this.renderWindow.render();
  }
  /**
 * 根据id 获取对应的编号
 */
  indexIdByPipeNodeId(nid) {
    for (let index = 0; index < this.validNodes.length; index++) {
      const node = this.validNodes[index];
      if (node.id == nid) {
        return index;
      }
    }
    return 0;
  }
  pointByPipeNodeId(nid) {
    for (let index = 0; index < this.validNodes.length; index++) {
      const node = this.validNodes[index];
      if (node.id == nid) {
        return [parseFloat(node.x), parseFloat(node.y), parseFloat(node.z)];
      }
    }
    return 0;
  }
  clearModeAddJg() {
    this.renderer.addActor(this.jgActor);
    this.renderer.addActor(this.scalarBarActor);
    this.modelClearShow();
    this.isJg = true; //显示结果
  }
  clearJgAddMode() {
    this.renderer.removeActor(this.scalarBarActor);
    this.renderer.removeActor(this.jgActor);
    this.modelShow();
    this.isJg = false; //不显示结果
  }
}

function pickOnMouseEvent(event) {
  if (vtkmodel.interactor.isAnimating()) {
    // We should not do picking when interacting with the scene
    return;
  }
  const [x, y] = eventToWindowXY(event);
  // console.log([x,y]);
  // vtkmodel.pointerActor.setVisibility(false);
  vtkmodel.hardwareSelector
    .getSourceDataAsync(vtkmodel.renderer, x, y, x, y)
    .then((result) => {
      if (result) {
        processSelections(result.generateSelection(x, y, x, y));
        // processSelections(result.generateSelection(x, y, x, y));
      } else {
        // processSelections(null);
      }
    });
}
function eventToWindowXY(event) {
  // We know we are full screen => window.innerXXX
  // Otherwise we can use pixel device ratio or else...
  const { clientX, clientY } = event;
  const [width, height] = vtkmodel.apiSpecificRenderWindow.getSize();
  const x = Math.round((width * clientX) / window.innerWidth);
  const y = Math.round(height * (1 - clientY / window.innerHeight)); // Need to flip Y
  return [x, y];
}
function processSelections(selections) {
  if (!selections || selections.length === 0) {//没有选择
    if (vtkmodel.lastActor == null) {

    } else {
      // vtkmodel.lastActor.getProperty().setColor(WHITE);
      // vtkmodel.renderWindow.render();
    }
    // vtkmodel.lastActor = null;
    return;
  }

  const {
    worldPosition: rayHitWorldPosition,
    compositeID,
    prop,
    propID,
    attributeID,
  } = selections[0].getProperties();
  if (vtkmodel.lastActor != null) {
    vtkmodel.lastActor.getProperty().setColor(WHITE);
    vtkmodel.renderWindow.render();
  }
  vtkmodel.nodeActors.forEach((nodeActor) => {
    if (prop == nodeActor.actor) {
      vtkmodel.selectObj = nodeActor.node;
      prop.getProperty().setColor(GREEN);
      vtkmodel.lastActor = prop;
      console.log(vtkmodel.selectObj );
    }
  });
  vtkmodel.pipeActors.forEach((pipeActor) => {
    if (prop == pipeActor.actor) {
      vtkmodel.selectObj = pipeActor.pipe;
      prop.getProperty().setColor(GREEN);
      vtkmodel.lastActor = prop;
      console.log(vtkmodel.selectObj );
    }
  });

  if (vtkmodel.isJg) {//结果数据选择cell
    //选择Cell
    const input = prop.getMapper().getInputData();
    if (!input.getCells()) {
      input.buildCells();
    }
    const cellPoints = input.getCellPoints(attributeID);
    if (cellPoints) {
      const pointIds = cellPoints.cellPointIds;
      // Find the closest cell point, and use that as cursor position
      const points = Array.from(pointIds).map((pointId) =>
        input.getPoints().getPoint(pointId)
      );
      // const scalarDataArray=input.getPointData().getScalars().getData();
      // pointIds.forEach(pointId=>{
      //   console.log(input.getPointData().getScalars().getName());
      //   console.log(scalarDataArray[pointId]);//节点标量数据
      // });
      vtkmodel.selectJgPointId =pointIds[0];
    }
  }
  vtkmodel.renderWindow.render();

 
}
const throttleMouseHandler = throttle(pickOnMouseEvent, 20);
const WHITE = [0, 0, 1];
const GREEN = [0.1, 0.8, 0.1];
const vtkmodel = new VtkModel();
export { vtkmodel };