/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */


import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import {ApplicationSecurityService, BillingReportService, HealthStatusService} from '../core/services';
import { ReportingGridComponent } from './reporting-grid/reporting-grid.component';
import { ToolbarComponent } from './toolbar/toolbar.component';

import { FileUtils } from '../core/util';
import { DICTIONARY, ReportingConfigModel } from '../../dictionary/global.dictionary';
import {ProgressBarService} from '../core/services/progress-bar.service';

@Component({
  selector: 'dlab-reporting',
  template: `
  <div class="base-retreat">
    <dlab-toolbar (rebuildReport)="rebuildBillingReport()"
                  (exportReport)="exportBillingReport()"
                  (setRangeOption)="setRangeOption($event)">
    </dlab-toolbar>
    <mat-divider></mat-divider>
    <dlab-reporting-grid (filterReport)="filterReport($event)" (resetRangePicker)="resetRangePicker()"></dlab-reporting-grid>
  </div>

  `,
  styles: [`
    footer {
      position: fixed;
      left: 0;
      bottom: 0;
      width: 100%;
      background: #a1b7d1;
      color: #ffffff;
      text-align: right;
      padding: 5px 15px;
      font-size: 18px;
      box-shadow: 0 9px 18px 15px #f5f5f5;
    }
  `]
})
export class ReportingComponent implements OnInit, OnDestroy {
  readonly DICTIONARY = DICTIONARY;

  @ViewChild(ReportingGridComponent, { static: false }) reportingGrid: ReportingGridComponent;
  @ViewChild(ToolbarComponent, { static: true }) reportingToolbar: ToolbarComponent;

  reportData: ReportingConfigModel = ReportingConfigModel.getDefault();
  filterConfiguration: ReportingConfigModel = ReportingConfigModel.getDefault();
  data: any;
  billingEnabled: boolean;
  admin: boolean;

  constructor(
    private billingReportService: BillingReportService,
    private healthStatusService: HealthStatusService,
    public toastr: ToastrService,
    private progressBarService: ProgressBarService,
    private applicationSecurityService: ApplicationSecurityService,
  ) { }

  ngOnInit() {
    this.getEnvironmentHealthStatus();
    this.buildBillingReport();
  }

  ngOnDestroy() {
    this.clearStorage();
  }

  getGeneralBillingData() {
    setTimeout(() => {this.progressBarService.startProgressBar(); } , 0);
    this.billingReportService.getGeneralBillingData(this.reportData)
      .subscribe(data => {
        this.data = data;
        this.reportingGrid.refreshData(this.data, this.data.report_lines);
        this.reportingGrid.setFullReport(this.data.is_full);

        this.reportingToolbar.reportData = this.data;
        if (!localStorage.getItem('report_period')) {
          localStorage.setItem('report_period', JSON.stringify({
            start_date: this.data['from'],
            end_date: this.data['to']
          }));
          this.reportingToolbar.setDateRange();
        }

        if (localStorage.getItem('report_config')) {
          this.filterConfiguration = JSON.parse(localStorage.getItem('report_config'));
          this.reportingGrid.setConfiguration(this.filterConfiguration);
        } else {
          this.getDefaultFilterConfiguration(this.data);
        }
        this.progressBarService.stopProgressBar();
      }, () => this.progressBarService.stopProgressBar());
  }

  rebuildBillingReport(): void {
    this.checkAutorize();
    this.buildBillingReport();

  }

  buildBillingReport() {
    this.clearStorage();
    this.resetRangePicker();
    this.reportData.defaultConfigurations();
    this.getGeneralBillingData();
  }

  private checkAutorize() {
    this.applicationSecurityService.isLoggedIn().subscribe( () => {
        this.getEnvironmentHealthStatus();
      }
    );
  }

  exportBillingReport(): void {
    this.billingReportService.downloadReport(this.reportData)
      .subscribe(
        data => FileUtils.downloadFile(data),
        () => this.toastr.error('Billing report export failed!', 'Oops!'));
  }

  getDefaultFilterConfiguration(data): void {
    const users = [], types = [], shapes = [], services = [], statuses = [], projects = [];

    data.report_lines.forEach((item: any) => {
      if (item.user && users.indexOf(item.user) === -1)
        users.push(item.user);

      if (item.status && statuses.indexOf(item.status.toLowerCase()) === -1)
        statuses.push(item.status.toLowerCase());

      if (item.project && projects.indexOf(item.project) === -1)
        projects.push(item.project);

      if (item['resource_type'] && types.indexOf(item['resource_type']) === -1)
        types.push(item['resource_type']);

      if (item.shape && types.indexOf(item.shape)) {
       if (item.shape.indexOf('Master') > -1) {
          for (let shape of item.shape.split('↵')) {
            shape = shape.replace('Master: ', '');
            shape = shape.replace(/Slave: /, '');
            shape = shape.replace(/\s+/g, '');
            shapes.indexOf(shape) === -1 && shapes.push(shape);
          }
        } else if (item.shape.match(/\d x \S+/)) {
          const parsedShape = item.shape.match(/\d x \S+/)[0].split(' x ')[1];
          if (shapes.indexOf(parsedShape) === -1) {
            shapes.push(parsedShape);
          }
        } else {
          shapes.indexOf(item.shape) === -1 && shapes.push(item.shape);
        }
      }

      if (item.product && services.indexOf(item.product) === -1)
        services.push(item.product);
    });

    if (!this.reportingGrid.filterConfiguration || !localStorage.getItem('report_config')) {
      this.filterConfiguration = new ReportingConfigModel(users, services, types, statuses, shapes, '', '', '', projects);
      this.reportingGrid.setConfiguration(this.filterConfiguration);
      localStorage.setItem('report_config', JSON.stringify(this.filterConfiguration));
    }
  }

  filterReport(event: ReportingConfigModel): void {
    this.reportData = event;
    this.getGeneralBillingData();
  }

  resetRangePicker() {
    this.reportingToolbar.clearRangePicker();
  }

  setRangeOption(dateRangeOption: any): void {
    this.reportData.date_start = dateRangeOption.start_date;
    this.reportData.date_end = dateRangeOption.end_date;
    this.getGeneralBillingData();
  }

  private clearStorage(): void {
    localStorage.removeItem('report_config');
    localStorage.removeItem('report_period');
  }

  private getEnvironmentHealthStatus() {
    this.healthStatusService.getEnvironmentHealthStatus()
      .subscribe((result: any) => {
        this.billingEnabled = result.billingEnabled;
        this.admin = result.admin;
      });
  }
}
