<template>
  <div
    v-if="chartData && height"
    :id="'lineWrapper' + facetId">
    <h4
      v-if="site && height > 0"
      class="subtitle"
      style="margin-bottom: 0;">{{ site }}</h4>
    <svg
      v-if="height > 0"
      :id="'line' + facetId"
      :width="chartWidth"
      :height="height"><!-- --></svg>
  </div>
</template>

<script type="text/javascript">
  import { mapState } from 'vuex'
  import * as d3 from 'd3';

  /**
   * Generic Facet - Line Chart
   *
   * Takes the incoming calculated object and displays an line chart.
   *
   * @since 0.4.0
   * @version 0.4.0
   */
  export default {
    name: 'LineChart',
    props: {
      /**
       * Facet Options set in app config.json
       */
      facetOptions: {
        type: [Object],
        default: () => ({
          facetId: 1311
        })
      },
      /**
       * incoming Chart Data
       */
      chartData: {
        type: Array,
        default: function () {
          return []
        }
      },
      /**
       * incoming Site name
       */
      site: {
        type: String,
        required: true,
        default: ''
      },
      /**
       * Pixel width of element.  Using pixel widths as props here to populate down from the grid-layout option.
       * @since 0.4.1
       */
      w: {
        type: Number,
        required: true,
        default: 1
      },
      /**
       * Pixel height of element.  Using pixel widths as props here to populate down from the grid-layout option.
       * @since 0.4.1
       */
      height: {
        type: Number,
        default: 60
      },
      /**
       * Id of grid item.  Using id as props here to populate down to the basic charts.
       * @since 0.4.1
       */
      facetId: {
        type: String,
        default: '170'
      }
    },
    data: function () {
      // @todo if we set the chart width above a certain number the chart sizes itself too large.  weird.
      return {
        xMargin: 30,
        yMargin: 20,
        yMax: null,
        xMax: null,
        xMin: null,
        color: 'blue',
        size: 3,
        dataPoints: null
      }
    },
    computed: {
      ...mapState([
        'layouts'
      ]),
      /**
       * Pixel computed width; based on prop width.  Used to set pie chart width.
       * @since 0.4.1
       */
      chartWidth: function () {
        // Sets chart width equal to gridItem width.
        let col = this.layouts.columnWidth;
        let margin = this.layouts.gridOptions.margins[0];
        return Math.round(col * this.w) + ((this.w - 1) * margin);
      },
      /**
       * Pixel computed height; based on prop width.  Used to set pie chart height.
       * @since 0.4.1
       */
      chartHeight: function () {
        if (this.site) {
          return (this.height - 25);
        }
        if (this.height < 0) {
          return 0
        }
      }
    },
    watch: {
      chartData () {
        this.drawChart();
      },
      chartWidth () {
        this.drawChart();
      }
    },
    mounted () {
      this.$nextTick(() => {
        this.drawChart();
      });
    },
    methods: {
      drawChart: function () {
        d3.select('#line' + this.facetId).html('');
        this.dataPoints = this.chartData;
        this.drawAxis();
        let color = ['black', 'lightblue', 'orange', 'green'];
        let i = 0;
        if (this.dataPoints) {
          this.dataPoints.forEach(function (resource) {
            this.drawLine(resource, color[i]);
            i++;
            if (i > 3) {
              i = 0;
            }
          }, this);
        }
      },
      getXScale: function () {
        this.xMax = this.dataPoints[0].length;
        return d3.scaleLinear().range([0, (this.chartWidth - this.xMargin * 1.5)])
          .domain([0, this.xMax]);
      },
      getYScale: function () {
        let maxs = []
        this.dataPoints.forEach(function (resource) {
          maxs.push(d3.max(resource))
        }, this)
        this.yMax = d3.max(maxs)
        return d3.scaleLinear().range([this.height - this.yMargin, this.yMargin])
          .domain([0, this.yMax])
      },
      drawAxis: function () {
        d3.select('#line' + this.facetId).append('g')
          .attr('transform', 'translate(' + this.xMargin + ',' + (this.height - this.$data.yMargin) + ')')
          .call(d3.axisBottom().scale(this.getXScale()))
        // y-axis is translated to (0,0)
        d3.select('#line' + this.facetId).append('g')
          .attr('transform', 'translate(' + this.$data.xMargin + ',0)')
          .call(d3.axisLeft().scale(this.getYScale()))
      },
      drawLine: function (listOfValues, color) {
        let lineValues = []
        for (let i = 0; i < listOfValues.length; i++) {
          lineValues.push({'x': i, 'y': listOfValues[i]})
        }
        let line = d3.line().x(d => this.cxTransformation(d.x) + 1).y(d => this.cyTransformation(d.y))
        d3.select('#line' + this.facetId).append('path').data([lineValues]).attr('class', 'line').attr('d', line).attr(
          'stroke', color).style('fill', 'none')
      },
      cxTransformation: function (x) {
        return ((this.chartWidth - this.xMargin * 1.5) / (this.xMax - this.xMin)) * (x - this.xMin) + this.xMargin;
      },
      cyTransformation: function (y) {
        return ((this.height - this.yMargin * 2) / this.yMax) * (this.yMax - y) + this.yMargin;
      }
    }
  }

</script>

<style type="text/css" scoped>
  .legend text, .axis text {
    font-size: 13px;
    fill: #333;
  }

  .axis path, .axis line {
    fill: none;
    stroke-width: 1px;
    stroke: #777;
  }

  .area {
    fill: lightblue;
  }
  .title:not(:last-child), .subtitle:not(:last-child) {
    margin-bottom: .5rem;
  }
</style>
