import axios from 'axios';
import moment from 'moment';
import React from 'react';
import { getDataStatistics } from '../../../api/icat/icatPlus';
import Loader from '../../Loader';
import ErrorUserMessage from '../../UserMessages/ErrorUserMessage';
import FileCountPanel from './FileCountPanel';
import VolumePanel from './VolumePanel';

class DataVolumeStatisticsPanel extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fetching: false,
      fetched: false,
      data: {
        releasedDate: this.getStats(),
        startDate: this.getStats(),
      },
      raw: {},
      message: {
        isError: false,
        text: null,
      },
    };
  }

  getStats() {
    return {
      volume: {
        sum: [],
        avg: [],
        max: [],
        median: [],
        summAcc: [],
      },
      fileCount: {
        sum: [],
        avg: [],
        max: [],
        median: [],
        summAcc: [],
      },
      accReleasedVolume: [],
      datasetsCount: [],
      accDatasetsCount: [],
      fileAverage: [],
      fileMax: [],
    };
  }

  parseData(buckets, stats, metric, fToApplyToData) {
    const data = [];
    for (const key in buckets) {
      let value = 0.01;
      if (metric) {
        value = buckets[key][stats][metric] ? buckets[key][stats][metric] : 0.0;
      } else {
        value = buckets[key][stats] ? buckets[key][stats].value : 0.0;
      }

      // This is to avoid problem in log scale
      value = value ? value : 0.0001;
      data.push({
        x: new Date(key),
        y: fToApplyToData ? fToApplyToData(value) : value,
      });
    }
    return data;
  }

  /**
  * Given an array of integers with valid years it will return a list of ranges composed by name, start and end for each month of the selected years
  * @param {String} years array with years. Example [2014, 2015]
  *
  *
  * For days in month:
  *  for (let i = 1; i < 13; i++) {
       let twoDigitsMonthNumber =  (i.toString().length == 2 ? i.toString() : "0" + i.toString());
       var stringDate = year + "-" + twoDigitsMonthNumber  + "-01";
       var date = new Date(stringDate);
       var momentData = moment(date);
       var daysinMonth = momentData.daysInMonth();

       for (let d = 1; d < daysinMonth + 1; d++) {
         let startDay =  momentData.format("YYYY-MM-DD");
         let endDay =  momentData.add(1, 'days').format("YYYY-MM-DD");

         var dict = {
           name: endDay,
           start: startDay ,
           end: endDay
         };
         ranges.push(dict);
       }
     }
    **/
  getYearRanges(years) {
    const ranges = [];
    years.forEach((year) => {
      for (let i = 1; i < 13; i++) {
        const twoDigitsMonthNumber =
          i.toString().length === 2 ? i.toString() : `0${i.toString()}`;
        const stringDate = `${year}-${twoDigitsMonthNumber}-01`;
        const date = new Date(stringDate);
        const daysinMonth = moment(date).daysInMonth();

        const dict = {
          name: `${year}-${twoDigitsMonthNumber}-${daysinMonth}`,
          start: `${year}-${twoDigitsMonthNumber}-01`,
          end: `${year}-${twoDigitsMonthNumber}-${daysinMonth}`,
        };
        ranges.push(dict);
      }
    });
    return ranges;
  }

  componentDidMount() {
    const _this = this;

    _this.setState({
      fetching: true,
      fetched: false,
    });

    axios
      .post(getDataStatistics(_this.props.user.sessionId), {
        ranges: _this.getYearRanges([
          2014,
          2015,
          2016,
          2017,
          2018,
          2019,
          2020,
          2021,
          2022,
          2023,
          2024,
        ]),
      })
      .then((response) => {
        if (response.status === 200) {
          const toTB = function (x) {
            return x / 1024 / 1024 / 1024 / 1024;
          };

          const volumeSum = _this.parseData(
            response.data.startDate.buckets,
            'volume_stats',
            'sum',
            toTB
          );
          let tmpVolumeAcc = 0;
          const volumeAcc = volumeSum.map((sum) => {
            tmpVolumeAcc = tmpVolumeAcc + sum.y;
            return { x: sum.x, y: tmpVolumeAcc };
          });

          const volumeReleasedSum = _this.parseData(
            response.data.releaseDate.buckets,
            'volume_stats',
            'sum',
            toTB
          );
          tmpVolumeAcc = 0;
          const volumeReleasedAcc = volumeReleasedSum.map((sum) => {
            tmpVolumeAcc = tmpVolumeAcc + sum.y;
            return { x: sum.x, y: tmpVolumeAcc };
          });

          _this.setState({
            fetching: false,
            fetched: true,
            raw: response.data,
            data: {
              releasedDate: {
                volume: {
                  sum: volumeReleasedSum,
                  avg: _this.parseData(
                    response.data.releaseDate.buckets,
                    'volume_stats',
                    'avg',
                    toTB
                  ),
                  max: _this.parseData(
                    response.data.releaseDate.buckets,
                    'volume_stats',
                    'max',
                    toTB
                  ),
                  median: _this.parseData(
                    response.data.releaseDate.buckets,
                    'volume_median',
                    null,
                    toTB
                  ),
                  sumAcc: volumeReleasedAcc,
                },
              },
              startDate: {
                volume: {
                  sum: volumeSum,
                  avg: _this.parseData(
                    response.data.startDate.buckets,
                    'volume_stats',
                    'avg',
                    toTB
                  ),
                  max: _this.parseData(
                    response.data.startDate.buckets,
                    'volume_stats',
                    'max',
                    toTB
                  ),
                  median: _this.parseData(
                    response.data.startDate.buckets,
                    'volume_median',
                    null,
                    toTB
                  ),
                  sumAcc: volumeAcc,
                },
                fileCount: {
                  sum: _this.parseData(
                    response.data.startDate.buckets,
                    'file_stats',
                    'sum'
                  ),
                  avg: _this.parseData(
                    response.data.startDate.buckets,
                    'file_stats',
                    'avg'
                  ),
                  max: _this.parseData(
                    response.data.startDate.buckets,
                    'file_stats',
                    'max'
                  ),
                  median: _this.parseData(
                    response.data.startDate.buckets,
                    'file_median'
                  ),
                },
              },
            },
          });
        }
      })
      .catch((error) => {
        _this.setState({
          message: {
            isError: true,
            text: error.message,
          },
        });
      });
  }

  render() {
    if (this.state.message.isError) {
      return <ErrorUserMessage text={this.state.message.text} />;
    }

    if (this.state.fetching) {
      return <Loader message="Loading statistics..." spacedOut />;
    }

    return (
      <>
        <br />
        <p className="text-secondary">
          Number of files produced for all the instruments. Note the log scale.
        </p>
        <FileCountPanel
          fetching={this.state.fetching}
          yTitle="Number of files"
          median={this.state.data.startDate.fileCount.median}
          average={this.state.data.startDate.fileCount.avg}
          sum={this.state.data.startDate.fileCount.sum}
          max={this.state.data.startDate.fileCount.max}
        />

        <br />
        <p className="text-secondary">Volume of dat produced and released</p>

        <VolumePanel
          fetching={this.state.fetching}
          yTitle="TB"
          median={this.state.data.startDate.volume.median}
          sum={this.state.data.startDate.volume.sum}
          sumAcc={this.state.data.startDate.volume.sumAcc}
          releaseSum={this.state.data.releasedDate.volume.sum}
          releaseSumAcc={this.state.data.releasedDate.volume.sumAcc}
        />
      </>
    );
  }
}

export default DataVolumeStatisticsPanel;
