import { FileFlow } from './../../resources/elements/flow-uploader';
import { PictureHelper, PictureType } from '../files/picture-helper';
import { bindable, autoinject, customElement, bindingMode, BindingEngine } from 'aurelia-framework';
import { computedFrom, Disposable } from 'aurelia-binding';
import { DialogService } from 'aurelia-dialog';
import { UIPictureEdit } from './ui-picture-edit';
import breeze from 'breeze-client';
import { UIInternal } from '../../utils/ui-internal';

@autoinject
@customElement('ui-pictures')
export class UIPictures {
  @bindable({ bindingMode: bindingMode.twoWay }) pictures: (PictureType & breeze.Entity)[];
  @bindable({ bindingMode: bindingMode.oneTime }) tagPropertyName: string;
  @bindable({ bindingMode: bindingMode.oneTime }) creatorPropertyPath: string;
  @bindable({ bindingMode: bindingMode.oneTime }) tagText: string | ((pict: any) => string);
  @bindable({ bindingMode: bindingMode.oneTime }) uploadButton: Element;
  @bindable({ bindingMode: bindingMode.oneTime }) pictureAddedFn: (file: FileFlow) => any;
  @bindable({ bindingMode: bindingMode.oneTime }) pictureUploadedFn: (file: FileFlow) => {};
  @bindable({ bindingMode: bindingMode.oneTime }) accept: string = 'picture';
  @bindable({ bindingMode: bindingMode.twoWay }) folderName: string;
  @bindable({ bindingMode: bindingMode.twoWay }) canEdit: boolean = false;
  @bindable({ bindingMode: bindingMode.twoWay }) canRotate: boolean = false;
  @bindable({ bindingMode: bindingMode.twoWay }) canDelete: boolean = false;
  @bindable({ bindingMode: bindingMode.twoWay }) canDownload: boolean = false;
  @bindable({ bindingMode: bindingMode.twoWay }) showEditActions: boolean = true;
  @bindable({ bindingMode: bindingMode.twoWay }) showName: boolean = false;
  @bindable({ bindingMode: bindingMode.oneTime }) showCreatorInformations: boolean = true;
  @bindable({ bindingMode: bindingMode.oneTime }) deletePictureFn: () => {};
  @bindable({ bindingMode: bindingMode.oneTime }) resizePicture = true;
  @bindable({ bindingMode: bindingMode.oneTime }) autoConvert = true;
  @bindable({ bindingMode: bindingMode.toView }) selectedPictures: (PictureType & breeze.Entity)[];
  @bindable({ bindingMode: bindingMode.oneTime }) useUniqueName: boolean = false;

  private disposables: Disposable[] = [];

  constructor(private pictureHelper: PictureHelper, private bindingEngine: BindingEngine, private dialogService: DialogService) { }

  @computedFrom("selectedPictures")
  get isSelectable(): boolean {
    return this.selectedPictures != null && isArray(this.selectedPictures);
  }

  public attached() {
    this.disposables.forEach(d => d.dispose());
    this.disposables.splice(0);

    this.pictures?.forEach(picture => {
      if (this.isSelectable) {
        this.addObserverIsSelected(picture);
      }
    });

    this.disposables.push(
      this.bindingEngine.collectionObserver(this.pictures).subscribe(changeRecords => {
        if (changeRecords.length > 0 && changeRecords[0].addedCount > 0) {
          let index = changeRecords[0].index;
          while (index < this.pictures.length) {
            let picture = this.pictures[index];
            if (this.isSelectable) {
              this.addObserverIsSelected(picture);
            }
            index++;
          }
        }
      })
    );
  }

  private addObserverIsSelected(picture: (PictureType & breeze.Entity)) {
    picture.isSelected = false;
    let observer = this.bindingEngine.propertyObserver(picture, 'isSelected');
    let disposable = observer.subscribe((newVal, oldVal) => {
      if (newVal === true) {
        this.selectedPictures.push(picture);
      }
      else {
        this.selectedPictures.remove(picture);
      }
    });
    this.disposables.push(disposable);
  }

  public detached() {
    this.disposables.forEach(d => d.dispose());
  }

  public getTag(picture): string {
    if (this.tagPropertyName != null && this.tagPropertyName.length > 0) {
      return picture[this.tagPropertyName]?.denomination._translation;
    }
    if (this.tagText != null) {
      if (this.tagText instanceof Function) {
        return this.tagText(picture)
      } else {
        return this.tagText;
      }
    }
    return null;
  }

  public getCreator(picture): string {
    if (this.creatorPropertyPath?.length > 0) {
      return UIInternal.getValue(picture, this.creatorPropertyPath);
    }
    return null;
  }

  public async rotatePicture(pictureEntity: (PictureType & breeze.Entity), clockwise: boolean) {
    await this.pictureHelper.rotatePicture(clockwise, pictureEntity);
  }

  public async editPicture(pictureEntity: (PictureType & breeze.Entity)) {
    await this.dialogService.open({ viewModel: UIPictureEdit, model: { url: pictureEntity.url, type: "url" }, lock: true }).whenClosed(async (closeResult) => {
      if (!closeResult.wasCancelled) {
        pictureEntity.url = null;
        let cache = await caches.open("pictures");
        cache.delete(closeResult.output);
        cache.add(closeResult.output);
        pictureEntity.url = closeResult.output;
        pictureEntity.entityAspect.rejectChanges();
      }
    });
  }

  public async downloadPicture(pictureEntity: (PictureType & breeze.Entity)) {
    await this.pictureHelper.downloadFile(pictureEntity);
  }
}

