import { Config } from '../config';
import { ServiceBase } from './../data/service-base';
import { DialogOpenResult, DialogService } from 'aurelia-dialog';
import { CustomDialogType, DialogBoxViewModel } from './dialogs/dialog-box';
import { autoinject } from 'aurelia-framework';
import * as breeze from 'breeze-client';
import { FloatingBoxViewModel } from './dialogs/floating-box';
import { BoxSize } from '../constants/constants';
import { ActionDialogBoxInputParameters } from '../model/common-model';

@autoinject
export class Box {
  constructor(private dialogService: DialogService, private config: Config) {
  }

  public showError(message: string, title: string, actions: ActionDialogBoxInputParameters[] = null, isTranslated: boolean = true, lock: boolean = true, keyboard: boolean = false) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        actions: actions,
        dialogType: CustomDialogType.Error,
        isTranslated: isTranslated
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-error-view-box");
        modalOverlay.classList.add("overlay-error-view-box");
      }
    });
  }

  public showQuestion(message: string, title: string, actions: ActionDialogBoxInputParameters[] = null, lock: boolean = true, keyboard: boolean = false) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        actions: actions,
        dialogType: CustomDialogType.Question
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-question-view-box");
        modalOverlay.classList.add("overlay-question-view-box");
      }
    });
  }

  public showWarning(message: string, title: string, actions: ActionDialogBoxInputParameters[] = null, lock: boolean = true, keyboard: boolean = false) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        actions: actions,
        dialogType: CustomDialogType.Warning
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-warning-view-box");
        modalOverlay.classList.add("overlay-warning-view-box");
      }
    });
  }

  public showNotification(message: string, title: string, actions: ActionDialogBoxInputParameters[] = null, lock: boolean = true, keyboard: boolean = false) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        actions: actions,
        dialogType: CustomDialogType.Notification
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-notification-view-box");
        modalOverlay.classList.add("overlay-notification-view-box");
      }
    });
  }

  public showEditDialog(viewModel, entityIdToEdit: number, title: string,
    optionsOrCallback?: Partial<ShowEditDialogOptions> | ((entity) => void | Promise<void>), optionsObj?: Partial<ShowEditDialogOptions>) {

    let callback: (entity) => void | Promise<void> = null;
    let options: Partial<ShowEditDialogOptions> = null;

    if (optionsOrCallback != null) {
      if (isFunction(optionsOrCallback)) {
        callback = optionsOrCallback;
        options = optionsObj;
      } else {
        options = optionsOrCallback;
      }
    } else if (optionsObj != null) {
      options = optionsObj;
    }

    if (options == null) {
      options = new ShowEditDialogOptions();
    }
    else {
      options = new ShowEditDialogOptions(options);
    }

    let model = {
      title: title,
      actions: options?.actions,
      dialogType: CustomDialogType.Edit,
      editVm: viewModel,
      param1: entityIdToEdit,
      callback: callback || options?.callback,
      canSave: options?.canSave,
      icon: options?.icon,
      position: options?.position,
      size: options?.size
    };
    Object.assign(model, options?.model)

    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: model,
      lock: options?.lock,
      keyboard: options?.keyboard,
      rejectOnCancel: false,
      position: (modalContainer, modalOverlay) => {
        if (options?.containerClass != null) {
          modalContainer.classList.add(options.containerClass);
        }
        if (options?.overlayClass != null) {
          modalOverlay.classList.add(options.overlayClass);
        }
      }
    });
  }

  public showCustomDialog(viewModel, entityIdToEdit: number, title: string,
    optionsOrCallback?: Partial<ShowEditDialogOptions> | ((entity) => void | Promise<void>), optionsObj?: Partial<ShowEditDialogOptions>) {

    let callback: (entity) => void | Promise<void> = null;
    let options: Partial<ShowEditDialogOptions> = null;

    if (optionsOrCallback != null) {
      if (isFunction(optionsOrCallback)) {
        callback = optionsOrCallback;
        options = optionsObj;
      } else {
        options = optionsOrCallback;
      }
    } else if (optionsObj != null) {
      options = optionsObj;
    }
    if (options == null) {
      options = new ShowEditDialogOptions();
    }
    else {
      options = new ShowEditDialogOptions(options);
    }

    let model = {
      title: title,
      dialogType: CustomDialogType.Custom,
      editVm: viewModel,
      param1: entityIdToEdit,
      callback: callback || options?.callback,
      canSave: options?.canSave,
      icon: options?.icon,
      position: options?.position,
      size: options?.size
    };
    Object.assign(model, options.model);

    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: model,
      lock: options?.lock,
      keyboard: options?.keyboard,
      rejectOnCancel: false,
      position: (modalContainer, modalOverlay) => {
        if (options?.containerClass != null) {
          modalContainer.classList.add(options.containerClass);
        }
        if (options?.overlayClass != null) {
          modalOverlay.classList.add(options.overlayClass);
        }
      }
    });
  }

  public showInput(message: string, title: string, required: boolean = true, lock: boolean = true, keyboard: boolean = false, icon: string = null) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        dialogType: CustomDialogType.Input,
        required: required,
        icon: icon
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-input-view-box");
        modalOverlay.classList.add("overlay-input-view-box");
      }
    });
  }

  public showRichInput(message: string, title: string, content: string, lock: boolean = true, keyboard: boolean = false, icon: string = null) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        dialogType: CustomDialogType.RichText,
        content: content,
        required: false,
        icon: icon
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-rich-text-view-box");
        modalOverlay.classList.add("overlay-rich-text-view-box");
      }
    });
  }

  public showSelect(message: string, title: string, service: ServiceBase<breeze.Entity>, optionsText: string, optionsValue: string, icon: string = null, lock: boolean = true, keyboard: boolean = false, isMultiple = true, select: number | Array<number> = null, sortColumn: string = null, filterProperties: Array<string> = null) {
    return this.dialogService.open({
      viewModel: DialogBoxViewModel,
      model: {
        message: message,
        title: title,
        dialogType: CustomDialogType.Select,
        service: service,
        optionsText: optionsText,
        optionsValue: optionsValue,
        icon: icon,
        isMultiple: isMultiple,
        select: select,
        sortColumn: sortColumn ?? optionsText,
        filterProperties: filterProperties ?? [optionsText]
      },
      lock: lock,
      keyboard: keyboard,
      rejectOnCancel: true,
      position: (modalContainer, modalOverlay) => {
        modalContainer.classList.add("container-select-view-box");
        modalOverlay.classList.add("overlay-select-view-box");
      }
    });
  }

  public showFloatingBox(viewModel: FloatingBoxViewModel, lock: boolean = true, keyboard: boolean = false) {
    let openPromise = this.dialogService.open(
      {
        host: this.config.containerConfig.DialogContainer.anchor,
        viewModel,
        view: viewModel.view,
        model: {
          dialogService: this.dialogService
        },
        lock: lock,
        keyboard: keyboard,
        rejectOnCancel: false,
        startingZIndex: 500, // allow (standard) modals to be show above the floating box
        position: (modalContainer, modalOverlay) => {
          modalContainer.classList.add('floating-box', viewModel.size);
          modalOverlay.classList.add('overlay-floating-box');
        }
      });
    //openPromise.then(openResult => viewModel.setDialogController(openResult.controller));
    openPromise.then(openResult => {
      if ((openResult as DialogOpenResult).controller) {
        viewModel.setDialogController((openResult as DialogOpenResult).controller);
      } else {
        debugger;
      }
    });
    return openPromise;
  }

}

export class ShowEditDialogOptions {
  callback?: (entity) => void | Promise<void>
  canSave: boolean;
  lock: boolean;
  keyboard: boolean;
  actions: ActionDialogBoxInputParameters[];
  icon: string;
  containerClass: string;
  overlayClass: string;
  position: 'left' | 'right';
  size: BoxSize;
  model: any;

  constructor(data?: Partial<ShowEditDialogOptions>) {
    Object.assign(this, {
      canSave: true,
      lock: true,
      keyboard: false,
      size: 'lg',
      position: 'right'
    }, data);
  }
}