
/*
 * Copyright 2017-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * © OpenCORD
 *
 * Visit http://guide.xosproject.org/devguide/addview/ for more information
 *
 * Created by teone on 3/21/16.
 */

(function () {
  'use strict';

  angular.module('xos.ceilometerDashboard')
  .directive('ceilometerSamples', function(_, $stateParams, $interval){
    return {
      restrict: 'E',
      scope: {},
      bindToController: true,
      controllerAs: 'vm',
      templateUrl: 'templates/ceilometer-samples.tpl.html',
      controller: function(Ceilometer) {

        this.chartColors = [
          '#286090',
          '#F7464A',
          '#46BFBD',
          '#FDB45C',
          '#97BBCD',
          '#4D5360',
          '#8c4f9f'
        ];

        this.chart = {
          series: [],
          labels: [],
          data: []
        }

        Chart.defaults.global.colours = this.chartColors;

        this.chartType = 'line';

        // TODO
        // check for name, if
        // - broadview.pt.packet-trace-lag-resolution
        // - broadview.pt.packet-trace-ecmp-resolution
        // draw a pie
        
        const pieStats = [
          'broadview.pt.packet-trace-lag-resolution',
          'broadview.pt.packet-trace-ecmp-resolution'
        ];
        let isApie = false;

        let refreshInterval = 60 * 1000;

        if($stateParams.name && $stateParams.tenant){
          this.name = $stateParams.name;
          // TODO rename tenant in resource_id
          this.tenant = $stateParams.tenant;

          if(pieStats.indexOf(this.name) > -1){
            isApie = true;
            this.chartType = 'pie';
            refreshInterval = 10 * 1000;
          }
        }
        else{
          throw new Error('Missing Name and Tenant Params!');
        }

        /**
         * Goes trough the array and format date to be used as labels
         *
         * @param Array data
         * @returns Array a list of labels
         */

        this.getLabels = (data) => {
          return data.reduce((list, item) => {
            let date = new Date(item.timestamp);
            list.push(`${date.getHours()}:${(date.getMinutes()<10?'0':'') + date.getMinutes()}:${date.getSeconds()}`);
            return list;
          }, []);
        };

        /**
         * Goes trough the array and return a flat array of values
         *
         * @param Array data
         * @returns Array a list of values
         */

        this.getData = (data) => {
          return data.reduce((list, item) => {
            list.push(item.volume);
            return list;
          }, []);
        }

        /**
         * Add a samples to the chart
         *
         * @param string resource_id
         */
        this.chartMeters = [];
        this.addMeterToChart = (resource_id) => {
          const resourcePos = _.findIndex(this.chartMeters, m => m.resource_id === resource_id);
          // if this meter is not yet rendered
          if (resourcePos < 0) {
            this.chart['data'].push(this.getData(_.sortBy(this.samplesList[resource_id], 'timestamp')));
            this.chart['labels'] = this.getLabels(_.sortBy(this.samplesList[resource_id], 'timestamp'));
            this.chart['series'].push(resource_id);
            this.chartMeters.push(this.samplesList[resource_id][0]); //use the 0 as are all samples for the same resource and I need the name
            _.remove(this.sampleLabels, {id: resource_id});
          }
          else {
            this.chart['data'][resourcePos] = this.getData(_.sortBy(this.samplesList[resource_id], 'timestamp'));
            this.chart['labels'] = this.getLabels(_.sortBy(this.samplesList[resource_id], 'timestamp'));
            this.chart['series'][resourcePos] = resource_id;
          }
        }

        this.removeFromChart = (meter) => {
          this.chart.data.splice(this.chart.series.indexOf(meter.resource_id), 1);
          this.chart.series.splice(this.chart.series.indexOf(meter.resource_id), 1);
          this.chartMeters.splice(_.findIndex(this.chartMeters, {resource_id: meter.resource_id}), 1);
          this.sampleLabels.push({
            id: meter.resource_id,
            name: meter.resource_name || meter.resource_id
          })
        };

        /**
         * Format samples to create a list of labels and ids
         */

        this.formatSamplesLabels = (samples) => {

          return _.uniq(samples, 'resource_id')
            .reduce((labels, item) => {
              labels.push({
                id: item.resource_id,
                name: item.resource_name || item.resource_id
              });

              return labels;
            }, []);
        }

        /**
        * Format data series in pie chart val
        */
       
        this.formatPieChartData = (samples) => {

          this.chart['labels'] = samples[0].metadata['lag-members'].replace(/\[|\]|'| /g, '').split(',');
          this.chart.options = {
            legend: {
              display: true
            }
          };
          samples = _.groupBy(samples, i => i.metadata['dst-lag-member']);
          
          // TODO show percentage in pie
          Chart.defaults.global.tooltipTemplate = '<%if (label){%><%=label%>: <%}%><%= value %>%';

          let data = _.reduce(this.chart.labels, (data, item) => {
            let length = samples[item] ? samples[item].length : 0;
            data.push(length);
            return data;
          }, []);

          let total = _.reduce(data, (d, t) => d + t);

          let percent = _.map(data, d => Math.round((d / total) * 100));

          console.log(total);

          this.chart['data'] = percent;
        };


        /**
         * Load the samples and format data
         */

        this.loader = true;
        this.showSamples = () => {
          // Ceilometer.getSamples(this.name, this.tenant) //fetch one
          let p;
          if (isApie){
            p = Ceilometer.getSamples(this.name, 30) //fetch all
          }
          else{
            p = Ceilometer.getSamples(this.name) //fetch all
          }

          p.then(res => {

            // rename things in UI
            res.map(m => {
              m.resource_name = m.resource_name.replace('mysite_onos_vbng', 'ONOS_FABRIC');
              m.resource_name = m.resource_name.replace('mysite_onos_volt', 'ONOS_CORD');
              m.resource_name = m.resource_name.replace('mysite_vbng', 'mysite_vRouter');
              return m;
            });
            // end rename things in UI

            // if I have to draw a pie skip the rest
            if(isApie){

              // TODO format data as pie
              this.formatPieChartData(res);
              return;
            }

            // setup data for visualization
            this.samplesList = _.groupBy(res, 'resource_id');
            this.sampleLabels = this.formatSamplesLabels(res);

            // add current meter to chart
            this.addMeterToChart(this.tenant);

          })
          .catch(err => {
            this.error = err.data.detail;
          })
          .finally(() => {
            this.loader = false;
          });
        };

        $interval(() => {
          this.showSamples();
        }, refreshInterval)
        this.showSamples();
      }
    }
  });
})();

