import { IBasicStrucElement } from '../page-object/i-page-structure';
import { PageElementMenu } from './page-element-menu';

export interface IPageElement {
  /* FINDERS */
  id: string;
  pageElement?: Cypress.Chainable;

  tooltip?: string | RegExp;
  tooltipCompareStrategy?: TextCompareStrategy;
  enabled?: boolean;
  visible?: boolean;
  exists?: boolean; // indicates if the field exists in the screen

  text?: string | RegExp;
  textCompareStrategy?: TextCompareStrategy;

  iconName?: string | RegExp;
  parentMenu?: PageElementMenu;

  validateDefaultFieldValues?(): void;
}

export enum TextCompareStrategy {
  EQUALS, INCLUDES, REGEX
}

export function doIfNotUndefined(variable: any, cb: () => void): void {
  if(typeof variable !== 'undefined') cb();
}

export enum PageElementType {
  FIELD, FORM, STATIC, RESULT_TABLE
}

export class PageElement implements IPageElement, IBasicStrucElement {
  mapTextCompareStrategy = new Map([
    [undefined, (text: string | RegExp) => this.getText().should('eq', text)],
    [TextCompareStrategy.EQUALS, (text: string | RegExp) => this.getText().should('eq', text)],
    [TextCompareStrategy.INCLUDES, (text: string | RegExp) => this.getText().should('contain', text)],
    [TextCompareStrategy.REGEX, (text: string | RegExp) => this.getText().should('match', text)]
  ]);

  get pageElement(): Cypress.Chainable {
    return this._pageElement || cy.get(this.id);
  }

  id: string;
  _pageElement: Cypress.Chainable | undefined;
  tooltip?: string | RegExp;
  tooltipCompareStrategy?: TextCompareStrategy;
  enabled?: boolean;
  visible?: boolean;
  exists?: boolean; // indicates if the field exists in the screen

  text?: string | RegExp;
  textCompareStrategy?: TextCompareStrategy;

  iconName?: string | RegExp;
  parentMenu?: PageElementMenu;

  constructor(ipe: IPageElement) {
    this.id = ipe.id;
    this._pageElement = ipe.pageElement;
    this.tooltip = ipe.tooltip;
    this.tooltipCompareStrategy = ipe.textCompareStrategy;

    this.visible = (typeof ipe.visible == 'boolean') ? ipe.visible : true;
    this.exists = (typeof ipe.exists == 'boolean') ? ipe.exists : true; // indicates if the field exists in the screen
    this.enabled = (typeof ipe.enabled == 'boolean') ? ipe.enabled : true;
    this.text = ipe.text;
    this.textCompareStrategy = ipe.textCompareStrategy;

    this.iconName = ipe.iconName;
    this.parentMenu = ipe.parentMenu;
  }

   mouseOver(): void {
    //  browser.actions().mouseMove(this.ipe.elementFinder).perform();
  }

  getText(): Cypress.Chainable {
    return this.pageElement.invoke('text');
  }

  validateDefaultFieldValues(): void {
    if (this.exists === false) {
      this.pageElement.should('not.exist');
      return;
    }
    doIfNotUndefined(
      this.tooltip, () => this.pageElement.invoke('attr', 'ng-reflect-message').should('include', this.tooltip));

    doIfNotUndefined(
      this.visible, () => this.visible ? this.pageElement.should('be.visible') : this.pageElement.should('not.be.visible'));

    doIfNotUndefined(
      this.text, () => this.mapTextCompareStrategy.get(this.textCompareStrategy)!(this.text!));

    doIfNotUndefined(
      this.iconName, () => this.getIconName().should('eq', this.iconName));
  }

  getIconName(): Cypress.Chainable { return this.pageElement; };

  validateTooltipShouldContainText(text: string): void {
    this.pageElement.invoke('attr', 'ng-reflect-message').should('include', text);
  }
}
