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 vtkGenericRenderWindow from '@kitware/vtk.js/Rendering/Misc/GenericRenderWindow';

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';

import vtk2DShape from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
import vtkArrowSource from '@kitware/vtk.js/Filters/Sources/ArrowSource';
import vtkArrow2DSource from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
import vtkConeSource from '@kitware/vtk.js/Filters/Sources/ConeSource';
import vtkAxesActor from '@kitware/vtk.js/Rendering/Core/AxesActor';

import vtkAnnotatedCubeActor from '@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor';
import vtkOrientationMarkerWidget from '@kitware/vtk.js/Interaction/Widgets/OrientationMarkerWidget';

import vtkCamera from '@kitware/vtk.js/Rendering/Core/Camera';

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 =null;
    this.renderer =null;
    this.renderWindow = null;


        //选取
        this.lastActor = null;
        this.nodeActors = []; //节点actor 数据
        this.pipeActors = []; //管道actor 数据
        this.interactor = null;
        this.apiSpecificRenderWindow = null;
        this.hardwareSelector = null;

     //模板数据
     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.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);
  
  }

  initMode(rootContainer){
    this.renderWindowWith =  vtkGenericRenderWindow.newInstance();
    this.renderWindowWith.setContainer(rootContainer);
    this.renderer = this.renderWindowWith.getRenderer();
    this.renderer.setBackground(0.0, 0.0, 0.0, 0.0)
    this.renderWindow = this.renderWindowWith.getRenderWindow();

    //选取
    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);
    this.hardwareSelector.setFieldAssociation(FieldAssociations.FIELD_ASSOCIATION_CELLS);

    document.addEventListener("mousemove", throttleMouseHandler);


    
    // //箭头
    // this.arrowActors = []; 
    // const viewColors = [
    //   [1, 0, 0], // sagittal
    //   [0, 1, 0], // coronal
    //   [0, 0, 1], // axial
    //   [0.5, 0.5, 0.5], // 3D
    // ];
    // // create axes
    // const axes = vtkAnnotatedCubeActor.newInstance();
    // axes.setDefaultStyle({
    //   text: '+X',
    //   fontStyle: 'bold',
    //   fontFamily: 'Arial',
    //   fontColor: 'black',
    //   fontSizeScale: (res) => res / 2,
    //   faceColor: createRGBStringFromRGBValues(viewColors[0]),
    //   faceRotation: 0,
    //   edgeThickness: 0.1,
    //   edgeColor: 'black',
    //   resolution: 400,
    // });
    // // axes.setXPlusFaceProperty({ text: '+X' });
    // axes.setXMinusFaceProperty({
    //   text: '-X',
    //   faceColor: createRGBStringFromRGBValues(viewColors[0]),
    //   faceRotation: 90,
    //   fontStyle: 'italic',
    // });
    // axes.setYPlusFaceProperty({
    //   text: '+Y',
    //   faceColor: createRGBStringFromRGBValues(viewColors[1]),
    //   fontSizeScale: (res) => res / 4,
    // });
    // axes.setYMinusFaceProperty({
    //   text: '-Y',
    //   faceColor: createRGBStringFromRGBValues(viewColors[1]),
    //   fontColor: 'white',
    // });
    // axes.setZPlusFaceProperty({
    //   text: '+Z',
    //   faceColor: createRGBStringFromRGBValues(viewColors[2]),
    // });
    // axes.setZMinusFaceProperty({
    //   text: '-Z',
    //   faceColor: createRGBStringFromRGBValues(viewColors[2]),
    //   faceRotation: 45,
    // });


    // // const vtkAxesActor = vtkAxesActor.newInstance();
    //   // create orientation widget
    // this.orientationWidget = vtkOrientationMarkerWidget.newInstance({
    //   actor: axes,
    //   interactor: this.renderWindow.getInteractor(),
    // });
    // this.orientationWidget.setEnabled(true);
    // this.orientationWidget.setViewportCorner(
    //   vtkOrientationMarkerWidget.Corners.BOTTOM_LEFT
    // );
    // this.orientationWidget.setViewportSize(0.15);
    // this.orientationWidget.setMinPixelSize(100);
    // this.orientationWidget.setMaxPixelSize(300);
  }
  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);
    };
  }


  //添加箭头
  addArrow(velocitys) {
    this.clearArrow();
    this.arrowActors=[];
    velocitys.forEach(velocity => {
      velocity.points.forEach(point => {
        // const initialValues = { 
        //   base:0,
        //   shape: 'arrow4points',
        //   center: [point.x,point.y,point.z],
        //   width: 3,height:10,direction:[
        //     velocity.vector[2],
        //     velocity.vector[0],
        //     velocity.vector[1]
        //   ] };
        // const vtk2d = vtk2DShape.newInstance(initialValues);

        const initialValues = { 
          base:0,
          center: [point.x,point.y,point.z],
          height:7,
          radius:2,
          resolution:3,
          direction:[
            velocity.vector[0],
            velocity.vector[1],
            velocity.vector[2]
          ] };
        const vtk2d = vtkConeSource.newInstance(initialValues);
        const mapper = vtkMapper.newInstance();
        mapper.setInputConnection(vtk2d.getOutputPort());
        const actor = vtkActor.newInstance();
        actor.setMapper(mapper);
        this.arrowActors.push(actor);
        // this.renderer.addActor(actor);
      })
    });
    // this.renderWindow.render();
  }
  clearArrow(){
    if(this.arrowActors){
      this.arrowActors.forEach(actor =>{
        this.renderer.removeActor(actor);
      });
    }
  }

  modelInit(validNodes, pipes) {
    this.renderWindowWith.resize();
    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();
    const cam = this.renderer.getActiveCamera();

    // const cam = vtkCamera.newInstance();
    // const cam =this.renderer.getActiveCamera();
    // this.renderer.setActiveCamera(cam);
    // cam.setFocalPoint(0, 0, 0);
    // cam.setPosition(0, 0, 10);
    // cam.setClippingRange(0.1, 2.0);
    // cam.setViewAngle(300);
    // console.log(
    //   cam.getPosition(),//摄像头位置
    //   cam.getViewAngle(),//相机视角 默认30
    //   cam.getFocalPoint(),//相机焦点
    //   cam.getViewUp(),//相机方向
    // );
    // position?: number[]; //摄像头位置
    // focalPoint?: number[]; //相机焦点
    // viewUp?: number[];//相机方向
    // directionOfProjection?: number[]; //相机到焦点的方向
    // parallelProjection?: boolean;//透视 平行
    // useHorizontalViewAngle?: boolean;//水平视角使用
    // viewAngle?: number;//相机视角
    // parallelScale?: number;//平行位置投影比例
    // clippingRange?: number[];//近远平面
    // windowCenter?: number[];//窗口中心位置 范围 ([-1,+1],[-1,+1])
    // viewPlaneNormal?: number[];//投影平面法线 （投影反方向）
    // useOffAxisProjection?: boolean;//离轴投影
    // screenBottomLeft?: number[];//左上角的点
    // screenBottomRight?: number[];//右上角的点
    // screenTopRight?: number[];//右上角的点 用于离轴投影
    // freezeFocalPoint?: boolean;
    // physicalTranslation?: number[];//物理翻译
    // physicalScale?: number;//物理尺度
    // physicalViewUp?: number[];//物理方向
    // physicalViewNorth?: number[];//物理北
   
    console.log("透视或平行相机", cam.getParallelProjection());
    // cam.setParallelProjection(true);
    //  console.log("透视或平行相机",cam.getParallelProjection());
    console.log("水平视角使用", cam.getUseHorizontalViewAngle());
    // cam.setUseHorizontalViewAngle(true);
    console.log("平行位置投影比例", cam.getParallelScale());
    // cam.setParallelScale(600);
    console.log("窗口中心位置", cam.getWindowCenter());//[0, 0]
    //  cam.setWindowCenter([1,-1]);
    console.log("相机视角", cam.getViewAngle());//30
    cam.setViewAngle(15);

    console.log("摄像头位置", cam.getPosition());//[495544.15625, 5403554.25, 9989.55990464236]
    cam.setPosition(495544.15625, 5403554.25, 9989.55990464236);
    console.log("相机焦点", cam.getFocalPoint());// [495544.15625, 5403554.25, 467.62999725341797]
    cam.setFocalPoint(495544.15625, 5403554.25, 467.62999725341797);
    console.log("相机方向", cam.getViewUp());//[0,1,0]
  // cam.setViewUp([0,1,1]);
    console.log("近远平面",cam.getClippingRange());// [9141.491986233214, 9913.53967078369]
    // cam.setClippingRange(9241.491986233214,9300.53967078369);
    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);
      });
    }
    this.renderer.addActor( this.axesActor);
  }


  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.clearArrow();
    this.modelShow();
    this.isJg = false; //不显示结果
  }
  clearAll() {
    this.renderer.removeActor(this.jgActor);
    this.renderer.removeActor(this.scalarBarActor);
    this.clearArrow();
    this.modelClearShow();
    this.renderWindow.render();
  }


  //选中指定点
  selectByNodeId(nid) {
    console.log("selectByNodeId", nid);
    if (this.isSelectNode) {
      if (this.lastActor != null) {
        this.lastActor.getProperty().setColor(WHITE);
      }
      this.nodeActors.forEach(nodeActor => {
        if (nid == nodeActor.node.id) {
          nodeActor.actor.getProperty().setColor(GREEN);

          this.renderWindow.render();
          this.lastActor = nodeActor.actor;
          this.selectObj = nodeActor.node;
          return;
        }
      });
    }
  }
  //选中指定管道
  selectByPipeId(pid) {
    console.log("selectByPipeId", pid);
    if (this.isSelectPipe) {
      if (this.lastActor != null) {
        this.lastActor.getProperty().setColor(WHITE);
      }
      this.pipeActors.forEach(pipeActor => {
        if (pid == pipeActor.pipe.id) {
          pipeActor.actor.getProperty().setColor(GREEN);
          this.renderWindow.render();
          this.lastActor = pipeActor.actor;
          this.selectObj = pipeActor.node;
          return;
        }
      });
    }
  }
}
function   createRGBStringFromRGBValues(rgb){
  if (rgb.length !== 3) {
    return 'rgb(0, 0, 0)';
  }
  return `rgb(${(rgb[0] * 255).toString()}, ${(rgb[1] * 255).toString()}, ${(
    rgb[2] * 255
  ).toString()})`;
}
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]);
  // if(!vtkmodel.getPointData){//没有数据
  //   return ;
  // }
  // console.log(vtkmodel.hardwareSelector.getPointData());
  // if(!vtkmodel.renderer.getActors().size==0){
  //   return;
  // }
  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
    if (vtkmodel.hardwareSelector.getFieldAssociation() ===
      FieldAssociations.FIELD_ASSOCIATION_POINTS) {//选择点

    } else {
      //选择Cell
      const input = prop.getMapper().getInputData();
      if (!input.getCells()) {
        input.buildCells();
        // return;
      }
      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();
        console.log(scalarDataArray[pointIds[0]]);//节点标量数据
        // pointIds.forEach(pointId=>{
        //   console.log(input.getPointData().getScalars().getName());
        //   console.log(scalarDataArray[pointId]);//节点标量数据
        // });
        vtkmodel.selectJgPointId = pointIds[0];
      }
    }

  } else {
    vtkmodel.renderWindow.render();
  }



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