text: import {CachedTrackRenderer} from '../../core';
  import PIXI from 'pixi.js';
  
  const Math = window.Math;
  
  export default class WIGRenderer extends CachedTrackRenderer{
  
      _height = null;
      _hoveredItemContainer;
  
      constructor(config){
          super();
          this._config = config;
          this._height = config.height;
      }
  
      get height() { return this._height; }
      set height(value) { this._height = value; }
  
      rebuildContainer(viewport, cache){
          super.rebuildContainer(viewport, cache);
          this._changeWig(viewport, cache.data, cache.coordinateSystem);
      }
  
      static getBaseScale(value) {
          return value > 0 ? (Math.log(value) / Math.log(10)) : 0;
      }
  
      _changeWig(viewport, wig, coordinateSystem) {
          if (wig === null || wig === undefined || coordinateSystem === null || coordinateSystem === undefined)
              return;
          if (this.dataContainer.children.length > 0) {
              this.dataContainer.removeChildren(0, this.dataContainer.children.length);
          }
          this._hoveredItemContainer = new PIXI.Container();
          {
              const {block, line} = this._renderItems(wig.items.aboveBaseAxis, this._config.wig.color, this._config.wig.lineColor, viewport, wig, coordinateSystem);
              this.dataContainer.addChild(block);
              this.dataContainer.addChild(line);
          }
          {
              const {block, line} = this._renderItems(wig.items.belowBaseAxis, this._config.wig.color, this._config.wig.lineColor, viewport, wig, coordinateSystem);
              this.dataContainer.addChild(block);
              this.dataContainer.addChild(line);
          }
          {
              const {block, line} = this._renderItems(wig.thresholdItems.aboveBaseAxis, this._config.wig.thresholdColor, this._config.wig.lineThresholdColor, viewport, wig, coordinateSystem);
              this.dataContainer.addChild(block);
              this.dataContainer.addChild(line);
          }
          {
              const {block, line} = this._renderItems(wig.thresholdItems.belowBaseAxis, this._config.wig.thresholdColor, this._config.wig.lineThresholdColor, viewport, wig, coordinateSystem);
              this.dataContainer.addChild(block);
              this.dataContainer.addChild(line);
          }
          this.dataContainer.addChild(this._hoveredItemContainer);
      }
  
      hoverItem() {
      }
  
      _renderItems(items, color, lineColor, viewport, wig, coordinateSystem) {
          const block = new PIXI.Graphics();
          const line = new PIXI.Graphics();
  
          const pixelsPerBp = viewport.factor;
  
          block.beginFill(color, 1);
          const lineThickness = 1;
          line.lineStyle(lineThickness, lineColor, 1);
  
          let count = 0;
  
          for (let i = 0; i < items.length; i++){
              const item = items[i];
              count++;
              if (item.points.length > 0) {
                  const start = item.points[0];
                  const padding = 0.5;
                  if (item.points.length === 1 || (wig.isDetailed && pixelsPerBp >= this._config.wig.detailedStyleStartingAtPixelsPerBP)){
                      const startX1 = Math.round(viewport.project.brushBP2pixel(start.startIndex - 0.5) + padding);
                      let startX2 = Math.round(viewport.project.brushBP2pixel(start.endIndex + 0.5) - padding);
  
                      if (startX1 === startX2) {
                          startX2++; // bar should have minimum 1px width
                      }
  
                      block.moveTo(startX1, this._getYValue(wig.baseAxis, coordinateSystem));
                      block.lineTo(startX1, this._getYValue(start.dataValue, coordinateSystem));
                      block.lineTo(startX2, this._getYValue(start.dataValue, coordinateSystem));
                      block.lineTo(startX2, this._getYValue(wig.baseAxis, coordinateSystem));
  
                      line.moveTo(startX1, this._getYValue(start.dataValue, coordinateSystem) - lineThickness / 2);
                      line.lineTo(startX2, this._getYValue(start.dataValue, coordinateSystem) - lineThickness / 2);
  
                      let prevX = startX2;
  
                      for (let j = 1; j < item.points.length; j++){
                          count++;
                          const point = item.points[j];
                          let startX = Math.round(viewport.project.brushBP2pixel(point.startIndex - 0.5) + padding);
                          const endX = Math.round(viewport.project.brushBP2pixel(point.endIndex + 0.5) - padding);
                          if (startX === prevX) {
                              startX ++;
                          }
                          block.lineTo(startX, this._getYValue(wig.baseAxis, coordinateSystem));
                          block.lineTo(startX, this._getYValue(point.dataValue, coordinateSystem));
                          block.lineTo(endX, this._getYValue(point.dataValue, coordinateSystem));
                          block.lineTo(endX, this._getYValue(wig.baseAxis, coordinateSystem));
  
                          line.moveTo(startX, this._getYValue(point.dataValue, coordinateSystem) - lineThickness / 2);
                          line.lineTo(endX, this._getYValue(point.dataValue, coordinateSystem) - lineThickness / 2);
  
                          prevX = endX;
                      }
  
                      block.lineTo(startX1, this._getYValue(wig.baseAxis, coordinateSystem));
                  }
                  else {
  
                      const startX1 = Math.round(viewport.project.brushBP2pixel(start.startIndex - 0.5) + padding);
                      const startX2 = Math.round(viewport.project.brushBP2pixel(start.endIndex + 0.5) - padding);
  
                      block.moveTo(startX1, this._getYValue(wig.baseAxis, coordinateSystem));
                      block.lineTo(startX1, this._getYValue(start.dataValue, coordinateSystem));
                      block.lineTo(startX2, this._getYValue(start.dataValue, coordinateSystem));
  
                      line.moveTo(startX1 - lineThickness / 2, this._getYValue(wig.baseAxis, coordinateSystem));
                      line.lineTo(startX1 - lineThickness / 2, this._getYValue(start.dataValue, coordinateSystem) - lineThickness / 2);
                      line.lineTo(startX1, this._getYValue(start.dataValue, coordinateSystem) - lineThickness / 2);
                      line.lineTo(startX2, this._getYValue(start.dataValue, coordinateSystem) - lineThickness / 2);
  
                      for (let j = 1; j < item.points.length; j++){
                          count++;
                          const point = item.points[j];
                          const x1 = Math.round(viewport.project.brushBP2pixel(point.startIndex - 0.5) + padding);
                          const x2 = Math.round(viewport.project.brushBP2pixel(point.endIndex + 0.5) - padding);
                          block.lineTo(x1, this._getYValue(point.dataValue, coordinateSystem));
                          block.lineTo(x2, this._getYValue(point.dataValue, coordinateSystem));
  
                          line.lineTo(x1, this._getYValue(point.dataValue, coordinateSystem) - lineThickness / 2);
                          line.lineTo(x2, this._getYValue(point.dataValue, coordinateSystem) - lineThickness / 2);
                      }
  
                      const end = item.points[item.points.length - 1];
                      const endX = Math.round(viewport.project.brushBP2pixel(end.endIndex + 0.5) - padding);
                      block.lineTo(endX, this._getYValue(wig.baseAxis, coordinateSystem));
                      block.lineTo(startX1, this._getYValue(wig.baseAxis, coordinateSystem));
  
                      line.lineTo(endX - lineThickness / 2, this._getYValue(end.dataValue, coordinateSystem) - lineThickness / 2);
                      line.lineTo(endX - lineThickness / 2, this._getYValue(wig.baseAxis, coordinateSystem) - lineThickness / 2);
                  }
              }
          }
          block.endFill();
          return {block, line};
      }
  
      _getYValue(value, coordinateSystem) {
          if (coordinateSystem.isLogScale) {
              value = WIGRenderer.getBaseScale(value);
          }
          return Math.round(this.height - this.height * (value - coordinateSystem.minimum) / (coordinateSystem.maximum - coordinateSystem.minimum));
      }
  
      onMove(viewport, cursor, data) {
          if (data && data.items && data.thresholdItems) {
              return this._checkItems(viewport, cursor, data.items.aboveBaseAxis, {above: true, threshold: false}) ||
                  this._checkItems(viewport, cursor, data.items.belowBaseAxis, {above: false, threshold: false}) ||
                  this._checkItems(viewport, cursor, data.thresholdItems.aboveBaseAxis, {above: true, threshold: true}) ||
                  this._checkItems(viewport, cursor, data.thresholdItems.belowBaseAxis, {above: false, threshold: true});
          }
          return null;
      }
  
      _checkItems(viewport, cursor, items, config){
          if (!items)
              return null;
          for (let i = 0; i < items.length; i++){
              const item = items[i];
              for (let j = 0; j < item.points.length; j++) {
                  const point = item.points[j];
                  if (cursor.x >= this.correctedXPosition(viewport.project.brushBP2pixel(point.startIndex - 0.5)) &&
                      cursor.x < this.correctedXPosition(viewport.project.brushBP2pixel(point.endIndex + 0.5))) {
                      return {...point, config};
                  }
              }
          }
          return null;
      }
  }
  