import {Component, Input, OnDestroy} from "@angular/core";
import {Stakeholder} from "../../openaireLibrary/monitor/entities/stakeholder";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {StakeholderUtils} from "../../utils/indicator-utils";
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
import {Subscriber, Subscription} from "rxjs";
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {StakeholderService} from "../../openaireLibrary/monitor/services/stakeholder.service";
import {UtilitiesService} from "../../openaireLibrary/services/utilities.service";
import {Session, User} from "../../openaireLibrary/login/utils/helper.class";
import {UserManagementService} from "../../openaireLibrary/services/user-management.service";
import {StringUtils} from "../../openaireLibrary/utils/string-utils.class";

declare var UIkit;

@Component({
  selector: 'edit-stakeholder',
  template: `
    <div *ngIf="stakeholderFb && user" [ngStyle]="{'max-height': maxHeight}"
         [class.uk-padding-small]="!paddingLarge" [class.uk-padding-large]="paddingLarge"
         class="uk-overflow-auto uk-padding-remove-bottom"
         [formGroup]="stakeholderFb">
      <div class="uk-grid" [class.uk-margin-small-bottom]="!paddingLarge" [class.uk-margin-large-bottom]="paddingLarge" uk-grid uk-height-match=".uk-form-hint">
        <div dashboard-input class="uk-width-1-2@m" [formInput]="stakeholderFb.get('name')" label="Name"
             placeholder="Write a name..."
             hint="Set a name for your profile."></div>
        <div dashboard-input class="uk-width-1-2@m" [formInput]="stakeholderFb.get('alias')"
             hint="Set an URL alias for your profile."
             label="URL Alias" placeholder="Write an alias..."></div>
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_id')"
             label="Index ID" placeholder="Write index ID.">
        </div>
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_name')"
             label="Index Name" placeholder="Write index name.">
        </div>
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_shortName')"
             label="Index Short Name" placeholder="Write index short name.">
        </div>
        <div dashboard-input class="uk-width-1-1" [type]="'textarea'" placeholder="Write a description..."
             hint="Write a description for your profile"
             [rows]="4" [formInput]="stakeholderFb.get('description')" label="Description"></div>
        <input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
        <div dashboard-input class="uk-width-1-1" [hideControl]="stakeholderFb.get('isUpload').value"
             hint="Upload or link the logo of your profile" [placeholder]="'Write link to the logo'"
             [formInput]="stakeholderFb.get('logoUrl')" label="Logo">
          <div *ngIf="!stakeholderFb.get('isUpload').value" class="uk-width-2-5@l uk-width-1-1">
            <div class="uk-grid uk-flex uk-flex-middle" uk-grid>
              <div class="uk-width-3-4@l uk-width-1-1 uk-flex uk-flex-center">
                <button class="uk-button uk-button-secondary uk-flex uk-flex-middle uk-flex-wrap"
                        (click)="file.click()">
                  <icon name="cloud_upload" [flex]="true"></icon>
                  <span class="uk-margin-small-left">Upload a file</span>
                </button>
              </div>
              <div class="uk-text-center uk-text-bold uk-width-expand">
                OR
              </div>
            </div>
          </div>
          <div *ngIf="stakeholderFb.get('isUpload').value" class="uk-width-1-1 uk-flex uk-flex-middle">
            <div class="uk-card uk-card-default uk-text-center uk-border-circle">
              <img class="uk-position-center" [src]="photo">
            </div>
            <div class="uk-margin-left">
              <button (click)="remove()" class="uk-button-secondary outlined uk-icon-button">
                <icon name="remove"></icon>
              </button>
            </div>
            <div class="uk-margin-small-left">
              <button class="uk-button-secondary uk-icon-button" (click)="file.click()">
                <icon name="edit"></icon>
              </button>
            </div>
          </div>
        </div>
        <div *ngIf="!stakeholderFb.get('isUpload').value && !secure" class="uk-margin-remove-top uk-width-1-1">
          <div class="uk-flex uk-flex-right" uk-grid>
            <div class="uk-width-3-5@l uk-width-1-1 uk-text-small uk-text-warning">
              <span class="uk-text-bold">Note:</span> Prefer urls like "<span class="uk-text-bold">https://</span>example.com/my-secure-image.png"
              instead of "<span class="uk-text-bold">http://</span>example.com/my-image.png".
              <span class="uk-text-bold">Browsers may not load non secure content.</span>
            </div>
          </div>
        </div>
        <div *ngIf="uploadError" class="uk-text-danger uk-width-1-1">{{uploadError}}</div>
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('visibility')"
             [placeholder]="'Select a status'"
             label="Status" hint="Select the visibility status of your profile"
             [options]="stakeholderUtils.statuses" type="select">
        </div>
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('type')"
             [placeholder]="'Select a type'" hint="Select the type of your profile"
             label="Type" [options]="types" type="select">
        </div>
        <ng-container
            *ngIf="!stakeholderFb.get('isDefault').value && isNew && stakeholderFb.get('type').valid && defaultStakeholdersOptions">
          <div [placeholder]="'Select a template'"
               hint="Select a template for your profile"
               dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('defaultId')"
               label="Template" [options]="defaultStakeholdersOptions" type="select"></div>
        </ng-container>
      </div>
    </div>`,
  styleUrls: ['edit-stakeholder.component.css']
})
export class EditStakeholderComponent implements OnDestroy {
  @Input()
  public maxHeight = 'none';
  @Input()
  public paddingLarge: boolean = false;
  @Input()
  public disableAlias: boolean = false;
  public stakeholderFb: FormGroup;
  public secure: boolean = false;
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
  public defaultStakeholdersOptions: Option[];
  public defaultStakeholders: Stakeholder[];
  public alias: string[];
  public stakeholder: Stakeholder;
  public isDefault: boolean;
  public isNew: boolean;
  public types: Option[];
  public properties: EnvProperties = properties;
  private subscriptions: any[] = [];
  /**
   * Photo upload
   * */
  public file: File;
  public photo: string | ArrayBuffer;
  public uploadError: string;
  public deleteCurrentPhoto: boolean = false;
  private maxsize: number = 200 * 1024;
  user: User;
  
  constructor(private fb: FormBuilder,
              private stakeholderService: StakeholderService,
              private utilsService: UtilitiesService, private userManagementService: UserManagementService,) {
  }
  
  ngOnDestroy() {
    this.reset();
  }
  
  public init(stakeholder: Stakeholder, alias: string[], defaultStakeholders: Stakeholder[], isDefault: boolean, isNew: boolean) {
    this.reset();
    this.deleteCurrentPhoto = false;
    this.stakeholder = stakeholder;
    this.alias = alias;
    this.defaultStakeholders = defaultStakeholders;
    this.isDefault = isDefault;
    this.isNew = isNew;
    this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
        this.user = user;
        this.types = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias);
        this.stakeholderFb = this.fb.group({
          _id: this.fb.control(this.stakeholder._id),
          defaultId: this.fb.control(this.stakeholder.defaultId),
          name: this.fb.control(this.stakeholder.name, Validators.required),
          description: this.fb.control(this.stakeholder.description),
          index_name: this.fb.control(this.stakeholder.index_name, Validators.required),
          index_id: this.fb.control(this.stakeholder.index_id, Validators.required),
          index_shortName: this.fb.control(this.stakeholder.index_shortName, Validators.required),
          creationDate: this.fb.control(this.stakeholder.creationDate),
          alias: this.fb.control(this.stakeholder.alias,
            [
              Validators.required,
              this.stakeholderUtils.aliasValidatorString(
                this.alias.filter(alias => alias !== this.stakeholder.alias)
              )]
          ),
          isDefault: this.fb.control((this.isDefault)),
          visibility: this.fb.control(this.stakeholder.visibility, Validators.required),
          type: this.fb.control(this.stakeholder.type, Validators.required),
          topics: this.fb.control(this.stakeholder.topics),
          isUpload: this.fb.control(this.stakeholder.isUpload),
          logoUrl: this.fb.control(this.stakeholder.logoUrl),
        });
        if (this.stakeholder.isUpload) {
          this.stakeholderFb.get('logoUrl').clearValidators();
          this.stakeholderFb.get('logoUrl').updateValueAndValidity();
        } else {
          this.stakeholderFb.get('logoUrl').setValidators([StringUtils.urlValidator()]);
          this.stakeholderFb.get('logoUrl').updateValueAndValidity();
        }
        this.subscriptions.push(this.stakeholderFb.get('isUpload').valueChanges.subscribe(value => {
          if (value == true) {
            this.stakeholderFb.get('logoUrl').clearValidators();
            this.stakeholderFb.updateValueAndValidity();
          } else {
            this.stakeholderFb.get('logoUrl').setValidators([StringUtils.urlValidator()]);
            this.stakeholderFb.updateValueAndValidity();
          }
        }));
        this.secure = (!this.stakeholderFb.get('logoUrl').value || this.stakeholderFb.get('logoUrl').value.includes('https://'));
        this.subscriptions.push(this.stakeholderFb.get('logoUrl').valueChanges.subscribe(value => {
          this.secure = (!value || value.includes('https://'));
        }));
        this.initPhoto();
        if (!isDefault) {
          this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => {
            this.onTypeChange(value, defaultStakeholders);
          }));
          this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, Validators.required));
        }
        if (!isNew) {
          if (this.isAdmin) {
            if (this.disableAlias) {
              setTimeout(() => {
                this.stakeholderFb.get('alias').disable();
              }, 0);
            }
          } else {
            setTimeout(() => {
              this.stakeholderFb.get('alias').disable();
              this.stakeholderFb.get('index_id').disable();
              this.stakeholderFb.get('index_name').disable();
              this.stakeholderFb.get('index_shortName').disable();
            }, 0);
          }
          setTimeout(() => {
            this.stakeholderFb.get('type').disable();
          }, 0);
        } else {
          setTimeout(() => {
            this.stakeholderFb.get('type').enable();
          }, 0);
        }
      }
    ));
  }
  
  public get isAdmin() {
    return Session.isPortalAdministrator(this.user);
  }
  
  public get disabled(): boolean {
    return (this.stakeholderFb && this.stakeholderFb.invalid) ||
      (this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) ||
      (this.uploadError && this.uploadError.length > 0);
  }
  
  public get dirty(): boolean {
    return this.stakeholderFb && this.stakeholderFb.dirty;
  }
  
  reset() {
    this.uploadError = null;
    this.stakeholderFb = null;
    this.subscriptions.forEach(subscription => {
      if (subscription instanceof Subscription) {
        subscription.unsubscribe();
      }
    });
  }
  
  onTypeChange(value, defaultStakeholders: Stakeholder[]) {
    this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, Validators.required));
    this.defaultStakeholdersOptions = [{
      label: 'New blank profile',
      value: '-1'
    }];
    defaultStakeholders.filter(stakeholder => stakeholder.type === value).forEach(stakeholder => {
      this.defaultStakeholdersOptions.push({
        label: 'Use ' + stakeholder.name + ' profile',
        value: stakeholder._id
      })
    });
  }
  
  public save(callback: Function, errorCallback: Function = null) {
    if (this.file) {
      this.stakeholderFb.get('alias').enable();
      this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/stakeholder/" + encodeURIComponent(this.stakeholderFb.value.alias), this.file).subscribe(res => {
        this.deletePhoto();
        this.removePhoto();
        this.stakeholderFb.get('logoUrl').setValue(res.filename);
        this.saveStakeholder(callback, errorCallback);
      }, error => {
        this.uploadError = "An error has been occurred during upload your image. Try again later";
        this.saveStakeholder(callback, errorCallback);
      }));
    } else if (this.deleteCurrentPhoto) {
      this.deletePhoto();
      this.saveStakeholder(callback, errorCallback);
    } else {
      this.saveStakeholder(callback, errorCallback);
    }
  }
  
  public saveStakeholder(callback: Function, errorCallback: Function = null) {
    if (this.isNew) {
      if (!this.stakeholderFb.value.isDefault) {
        let stakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.value.defaultId);
        this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.value,
          (stakeholder ? stakeholder.topics : [])));
      }
      this.removePhoto();
      this.subscriptions.push(this.stakeholderService.buildStakeholder(this.properties.monitorServiceAPIURL,
        this.stakeholderFb.value).subscribe(stakeholder => {
        UIkit.notification(stakeholder.name + ' has been <b>successfully created</b>', {
          status: 'success',
          timeout: 6000,
          pos: 'bottom-right'
        });
        callback(stakeholder);
      }, error => {
        UIkit.notification('An error has occurred. Please try again later', {
          status: 'danger',
          timeout: 6000,
          pos: 'bottom-right'
        });
        if (errorCallback) {
          errorCallback(error)
        }
      }));
    } else {
      this.stakeholderFb.get('alias').enable();
      this.stakeholderFb.get('type').enable();
      this.stakeholderFb.get('index_id').enable();
      this.stakeholderFb.get('index_name').enable();
      this.stakeholderFb.get('index_shortName').enable();
      this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.stakeholderFb.value).subscribe(stakeholder => {
        UIkit.notification(stakeholder.name + ' has been <b>successfully saved</b>', {
          status: 'success',
          timeout: 6000,
          pos: 'bottom-right'
        });
        callback(stakeholder);
      }, error => {
        UIkit.notification('An error has occurred. Please try again later', {
          status: 'danger',
          timeout: 6000,
          pos: 'bottom-right'
        });
      }));
    }
  }
  
  fileChangeEvent(event) {
    if (event.target.files && event.target.files[0]) {
      this.file = event.target.files[0];
      if (this.file.type !== 'image/png' && this.file.type !== 'image/jpeg') {
        this.uploadError = 'You must choose a file with type: image/png or image/jpeg!';
        this.stakeholderFb.get('isUpload').setValue(false);
        this.stakeholderFb.get('isUpload').markAsDirty();
        this.removePhoto();
      } else if (this.file.size > this.maxsize) {
        this.uploadError = 'File exceeds size\'s limit! Maximum resolution is 256x256 pixels.';
        this.stakeholderFb.get('isUpload').setValue(false);
        this.stakeholderFb.get('isUpload').markAsDirty();
        this.removePhoto();
      } else {
        this.uploadError = null;
        const reader = new FileReader();
        reader.readAsDataURL(this.file);
        reader.onload = () => {
          this.photo = reader.result;
          this.stakeholderFb.get('isUpload').setValue(true);
          this.stakeholderFb.get('isUpload').markAsDirty();
        };
      }
    }
  }
  
  initPhoto() {
    if (this.stakeholderFb.value.isUpload) {
      this.photo = this.properties.utilsService + "/download/" + this.stakeholderFb.get('logoUrl').value;
    }
  }
  
  removePhoto() {
    if (this.file) {
      if (typeof document != 'undefined') {
        (<HTMLInputElement>document.getElementById("photo")).value = "";
      }
      this.initPhoto();
      this.file = null;
    }
  }
  
  remove() {
    this.stakeholderFb.get('isUpload').setValue(false);
    this.stakeholderFb.get('isUpload').markAsDirty();
    this.removePhoto();
    this.stakeholderFb.get('logoUrl').setValue(null);
    if (this.stakeholder.isUpload) {
      this.deleteCurrentPhoto = true;
    }
  }
  
  public deletePhoto() {
    if (this.stakeholder.logoUrl) {
      this.subscriptions.push(this.utilsService.deletePhoto(this.properties.utilsService + '/delete/stakeholder/' + this.stakeholder.logoUrl).subscribe());
    }
  }
}
