/*
 * 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, ViewChild, Inject, OnDestroy } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { ApplicationSecurityService, ManageUngitService, StorageService } from '../../core/services';

import { FolderTreeComponent } from './folder-tree/folder-tree.component';
import { BucketBrowserService } from '../../core/services/bucket-browser.service';
import { FileUtils, HelpUtils } from '../../core/util';
import { BucketDataService } from './bucket-data.service';
import { BucketConfirmationDialogComponent } from './bucket-confirmation-dialog/bucket-confirmation-dialog.component';
import { HttpEventType } from '@angular/common/http';
import { CopyPathUtils } from '../../core/util/copyPathUtils';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
  selector: 'datalab-bucket-browser',
  templateUrl: './bucket-browser.component.html',
  styleUrls: ['./bucket-browser.component.scss', './upload-window.component.scss']
})
export class BucketBrowserComponent implements OnInit, OnDestroy {
  public readonly uploadingQueueLength: number = 4;
  public readonly maxFileSize: number = 4294967296;
  public readonly refreshTokenLimit = 1500000;

  private unsubscribe$ = new Subject();
  private isTokenRefreshing = false;
  public addedFiles = [];
  public folderItems = [];
  public originFolderItems = [];
  public objectPath;
  public path = '';
  public pathInsideBucket = '';
  public bucketName = '';
  public endpoint = '';
  public selectedFolder: any;
  public selectedFolderForAction: any;
  public selected: any[];
  public bucketStatus;
  public allDisable: boolean;
  public isActionsOpen: boolean;
  public folders: any[];
  public selectedItems;
  public searchValue: string;
  public isQueueFull: boolean;
  public isSelectionOpened: any;
  public isFilterVisible: boolean;
  public buckets;
  public isFileUploading: boolean;
  public cloud: string;

  @ViewChild(FolderTreeComponent, { static: true }) folderTreeComponent;

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    public toastr: ToastrService,
    public dialog: MatDialog,
    public dialogRef: MatDialogRef<BucketBrowserComponent>,
    private manageUngitService: ManageUngitService,
    private _fb: FormBuilder,
    private bucketBrowserService: BucketBrowserService,
    public bucketDataService: BucketDataService,
    private auth: ApplicationSecurityService,
    private storage: StorageService,
  ) { }

  ngOnInit() {
    this.bucketName = this.data.bucket;
    this.endpoint = this.data.endpoint;
    this.bucketDataService.refreshBucketdata(this.bucketName, this.endpoint);
    this.bucketStatus = this.data.bucketStatus;
    this.buckets = this.data.buckets;
    this.cloud = this.getCloud();
    // this.cloud = 'azure';
  }

  ngOnDestroy() {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

  public getTokenValidTime(): number {
    const token = JSON.parse(atob(this.storage.getToken().split('.')[1]));
    return token.exp * 1000 - new Date().getTime();
  }

  private refreshToken(): void {
    this.isTokenRefreshing = true;
    this.auth.refreshToken()
      .pipe(
        takeUntil(this.unsubscribe$)
      )
      .subscribe(tokens => {
        this.storage.storeTokens(tokens);
        this.isTokenRefreshing = false;
        this.sendFile();
      });
  }

  public showItem(item): void {
    const flatItem = this.folderTreeComponent.nestedNodeMap.get(item);
    this.folderTreeComponent.showItem(flatItem);
  }

  public closeUploadWindow(): void {
    this.addedFiles = [];
  }

  public toggleSelectedFile(file, type): void {
    console.log(file, type);
    type === 'file' 
      ? file.isSelected = !file.isSelected 
      : file.isFolderSelected = !file.isFolderSelected;
    this.selected = this.folderItems.filter(item => item.isSelected);
    this.selectedFolderForAction = this.folderItems.filter(item => item.isFolderSelected);
    this.selectedItems = [...this.selected, ...this.selectedFolderForAction];
    this.isActionsOpen = false;
  }

  filesPicked(files): void {
    Array.prototype.forEach.call(files, file => {
      this.addedFiles.push(file.webkitRelativePath);
    });
  }

  public dissableAll(event): void {
    this.allDisable = event;
  }

  public handleFileInput(event): void {
    const fullFilesList = Object['values'](event.target.files);
    if (fullFilesList.length > 0) {
      const files = fullFilesList.filter(v => v.size < this.maxFileSize);
      const toBigFile = fullFilesList.length !== files.length;
      const toMany = files.length > 50;
      if (toMany) {
        files.length = 50;
      }

      if (toBigFile || toMany) {
        this.dialog.open(BucketConfirmationDialogComponent, {
          data: {
            items: { toBig: toBigFile, toMany: toMany }, type: 'upload_limitation'
          }, width: '550px'
        })
          .afterClosed().subscribe((res) => {
            if (res) {
              this.checkQueue(files);
            }
          });
      } else {
        this.checkQueue(files);
      }
    }
    event.target.value = '';
  }

  private checkQueue(files) {
    if (this.refreshTokenLimit > this.getTokenValidTime()) {
      this.isTokenRefreshing = true;
      this.auth.refreshToken()
        .pipe(
          takeUntil(this.unsubscribe$)
        )
        .subscribe(v => {
          this.uploadingQueue(files);
          this.isTokenRefreshing = false;
        });
    } else {
      this.uploadingQueue(files);
    }
  }

  private async uploadingQueue(files) {
    if (files.length) {
      let askForAll = true;
      let skipAll = false;

      const folderFiles = this.folderItems.reduce((existFiles, item) => {
        if (!item.children) {
          existFiles.push(item.item);
        }
        return existFiles;
      }, []);

      for (const file of files) {
        const existFile = folderFiles.find(v => v === file['name']);
        const uploadItem = {
          name: file['name'],
          file: file,
          size: file.size,
          path: this.path,
        };

        if (existFile && askForAll) {
          const result = await this.openResolveDialog(existFile);
          if (result) {
            askForAll = !result.forAll;
            if (result.forAll && !result.replaceObject) {
              skipAll = true;
            }
            if (result.replaceObject) {
              this.addedFiles.push(uploadItem);
              this.uploadNewFile(uploadItem);
            }
          }
        } else if (!existFile || (existFile && !askForAll && !skipAll)) {
          this.addedFiles.push(uploadItem);
          this.uploadNewFile(uploadItem);
        }
      }
    }
    setTimeout(() => {
      const element = document.querySelector('#upload-list');
      element && element.scrollIntoView({ block: 'end', behavior: 'smooth' });
    }, 10);
  }

  async openResolveDialog(existFile) {
    const dialog = this.dialog.open(BucketConfirmationDialogComponent, {
      data: { items: existFile, type: 'resolve_conflicts' }, width: '550px'
    });
    return dialog.afterClosed().toPromise().then(result => {
      return Promise.resolve(result);
    });
  }

  public onFolderClick(event): void {
    this.searchValue = '';
    this.clearSelection();
    this.selectedFolder = event.flatNode;
    if (this.isSelectionOpened) {
      this.isSelectionOpened = false;
    }
    this.folderItems = event.element ? event.element.children : event.children;
    if (this.folderItems) {
      this.folders = this.folderItems.filter(v => v.children);
      const files = this.folderItems.filter(v => !v.children).sort((a, b) => a.item > b.item ? 1 : -1);
      this.folderItems = [...this.folders, ...files];
      this.objectPath = event.pathObject;
      this.path = event.path;
      this.originFolderItems = this.folderItems.map(v => v);
      this.pathInsideBucket = this.path.indexOf('/') !== -1 
        ? this.path.slice(this.path.indexOf('/') + 1) + '/' 
        : '';
      this.folderItems.forEach(item => item.isSelected = false);
    }
  }

  public filterObjects(): void {
    this.folderItems = this.originFolderItems.filter(v => v.item.toLowerCase().indexOf(this.searchValue.toLowerCase()) !== -1);
  }

  private clearSelection(): void {
    this.folderItems.forEach(item => item.isSelected = false);
    this.folderItems.forEach(item => item.isFolderSelected = false);
    this.selected = this.folderItems.filter(item => item.isSelected);
    this.selectedFolderForAction = this.folderItems.filter(item => item.isFolderSelected);
    this.selectedItems = [];
  }

  public deleteAddedFile(file): void {
    if (file.subscr && file.request) {
      this.dialog.open(BucketConfirmationDialogComponent, { data: { items: file, type: 'cancel' }, width: '550px' })
        .afterClosed().subscribe((res) => {
          res && file.subscr.unsubscribe();
          res && this.addedFiles.splice(this.addedFiles.indexOf(file), 1);
          this.isFileUploading = this.addedFiles.some(v => v.status === 'uploading');
          this.sendFile();
        }, () => {
          this.isFileUploading = this.addedFiles.some(v => v.status === 'uploading');
          this.sendFile();
        });
    } else {
      this.addedFiles.splice(this.addedFiles.indexOf(file), 1);
      this.isFileUploading = this.addedFiles.some(v => v.status === 'uploading');
      this.sendFile();
    }
  }

  private uploadNewFile(file): void {
    const path = file.path.indexOf('/') !== -1 ? this.path.slice(this.path.indexOf('/') + 1) : '';
    const fullPath = path ? `${path}/${file.name}` : file.name;
    const formData = new FormData();
    formData.append('size', file.file.size);
    formData.append('object', fullPath);
    formData.append('bucket', this.bucketName);
    formData.append('endpoint', this.endpoint);
    formData.append('file', file.file);
    file.status = 'waiting';

    file.request = this.bucketBrowserService.uploadFile(formData);
    this.sendFile(file);
  }

  public sendFile(file?): void {
    const waitUploading = this.addedFiles.filter(v => v.status === 'waiting');
    const uploading = this.addedFiles.filter(v => v.status === 'uploading');
    this.isQueueFull = !!waitUploading.length;
    this.isFileUploading = this.addedFiles.some(v => v.status === 'uploading');
    // console.log((this.getTokenValidTime() / 1000 / 60 ).toFixed(0) + ' minutes');
    if ((this.refreshTokenLimit > this.getTokenValidTime()) && !this.isTokenRefreshing) {
      this.refreshToken();
    }

    if (waitUploading.length && uploading.length < this.uploadingQueueLength) {
      if (!file) {
        file = waitUploading[0];
      }
      
      file.status = 'uploading';
      this.isFileUploading = this.addedFiles.some(v => v.status === 'uploading');
      this.isQueueFull = this.addedFiles.some(v => v.status === 'waiting');
      file.subscr = file.request
        .subscribe(
          (event: any) => {
            if (event.type === HttpEventType.UploadProgress) {
              file.progress = Math.round(95 * event.loaded / event.total);
              if (file.progress === 95 && !file.interval) {
                file.interval = setInterval(() => {
                  if (file.progress < 99) {
                    return file.progress++;
                  }
                }, file.size < 1094967296 ? 12000 : 20000);
              }
            } else if (event['type'] === HttpEventType.Response) {
              window.clearInterval(file.interval);
              file.status = 'uploaded';
              delete file.request;
              this.sendFile(this.addedFiles.find(v => v.status === 'waiting'));
              this.bucketDataService.refreshBucketdata(this.bucketName, this.endpoint);
            }
          }, 
          error => {
            window.clearInterval(file.interval);
            file.status = 'failed';
            delete file.request;
            this.sendFile(this.addedFiles.find(v => v.status === 'waiting'));
          }
        );
    }
  }

  public refreshBucket(): void {
    this.path = '';
    this.bucketDataService.refreshBucketdata(this.bucketName, this.endpoint);
    this.isSelectionOpened = false;
  }

  public openBucket($event): void {
    this.bucketName = $event.name;
    this.endpoint = $event.endpoint;
    this.path = '';
    this.bucketDataService.refreshBucketdata(this.bucketName, this.endpoint);
    this.isSelectionOpened = false;
    this.cloud = this.getCloud();
  }

  private getCloud(): string {
    return this.buckets.filter(v => v.children.some(bucket => {
      return bucket.name === this.bucketName;
    }))[0].cloud.toLowerCase();
  }

  public createFolder(folder): void {
    this.allDisable = true;
    this.folderTreeComponent.addNewItem(folder, '', false);
  }

  public fileAction(action): void {
    const selected = this.folderItems.filter(item => item.isSelected);
    const folderSelected = this.folderItems.filter(item => item.isFolderSelected);
    if (action === 'download') {
      this.clearSelection();
      this.isActionsOpen = false;
      const path = encodeURIComponent(`${this.pathInsideBucket}${selected[0].item}`);
      selected[0]['isDownloading'] = true;
      this.folderItems.forEach(item => item.isSelected = false);
      this.bucketBrowserService.downloadFile(`/${this.bucketName}/object/${path}/endpoint/${this.endpoint}/download`)
        .pipe(
          takeUntil(this.unsubscribe$)
        )
        .subscribe(
          event => {
            if (event['type'] === HttpEventType.DownloadProgress) {
              selected[0].progress = Math.round(100 * event['loaded'] / selected[0].object.size);
            }
            if (event['type'] === HttpEventType.Response) {
              FileUtils.downloadBigFiles(event['body'], selected[0].item);
              setTimeout(() => {
                selected[0]['isDownloading'] = false;
                selected[0].progress = 0;
              }, 1000);
            }
          }, 
          error => {
            this.toastr.error(error.message || 'File downloading error!', 'Oops!');
            selected[0]['isDownloading'] = false;
          }
        );
    }

    if (action === 'delete') {
      const itemsForDeleting = [...folderSelected, ...selected];
      const objects = itemsForDeleting.map(obj => obj.object.object);
      let dataForServer = [];
      objects.forEach(object => {
        dataForServer.push(...this.bucketDataService.serverData.map(v => v.object).filter(v => v.indexOf(object) === 0));
      });
      dataForServer = [...dataForServer, ...objects].filter((v, i, arr) => i === arr.indexOf(v));
      this.dialog.open(BucketConfirmationDialogComponent, { data: { items: itemsForDeleting, type: 'delete' }, width: '550px' })
        .afterClosed().subscribe((res) => {
          !res && this.clearSelection();
          res && this.bucketBrowserService.deleteFile({
            bucket: this.bucketName, endpoint: this.endpoint, 'objects': dataForServer
          })
            .pipe(
              takeUntil(this.unsubscribe$)
            )
            .subscribe(() => {
              this.bucketDataService.refreshBucketdata(this.bucketName, this.endpoint);
              this.toastr.success('Objects successfully deleted!', 'Success!');
              this.clearSelection();
            }, error => {
              this.toastr.error(error.message || 'Objects deleting error!', 'Oops!');
              this.clearSelection();
            });
        });

    }
  }

  public toogleActions(): void {
    this.isActionsOpen = !this.isActionsOpen;
  }

  public closeActions(): void {
    this.isActionsOpen = false;
  }

  public copyPath(): void {
    const selected = this.folderItems.filter(item => item.isSelected || item.isFolderSelected)[0];
    const cloud = this.getCloud();
    const protocol = HelpUtils.getBucketProtocol(cloud);
    if (cloud !== 'azure') {
      CopyPathUtils.copyPath(protocol + selected.object.bucket + '/' + selected.object.object);
    } else {
      const bucketName = selected.object.bucket;
      const accountName = this.bucketName.replace(selected.object.bucket, '').slice(0, -1);
      const azureBucket = bucketName + '@' + accountName + '.blob.core.windows.net' + '/' + selected.object.object;
      CopyPathUtils.copyPath(protocol + azureBucket);
    }
    this.clearSelection();
    this.isActionsOpen = false;
    this.toastr.success('Object path successfully copied!', 'Success!');
  }

  public toggleBucketSelection(): void {
    this.isSelectionOpened = !this.isSelectionOpened;
  }

  public closeFilterInput(): void {
    this.isFilterVisible = false;
    this.searchValue = '';
    this.filterObjects();
  }
}
