import { EventManager } from '@angular/platform-browser';
import { NgZone } from '@angular/core';

export class MDCEventPlugin {
  public manager: EventManager;
  protected eventMap: object = {
    MDCAutoInitEnd: 'MDCAutoInit:End',
    MDCComponentAttachTo: 'MDCComponent:attachTo',
    MDCDialogAccept: 'MDCDialog:accept',
    MDCDialogCancel: 'MDCDialog:cancel',
    MDCPersistentDrawerOpen: 'MDCPersistentDrawer:open',
    MDCPersistentDrawerClose: 'MDCPersistentDrawer:close',
    MDCTemporaryDrawerOpen: 'MDCTemporaryDrawer:open',
    MDCTemporaryDrawerClose: 'MDCTemporaryDrawer:close',
    MDCIconButtonToggleChange: 'MDCIconButtonToggle:change',
    MDCIconToggleChange: 'MDCIconToggle:change',
    MDCMenuSelected: 'MDCMenu:selected',
    MDCMenuCancel: 'MDCMenu:cancel',
    MDCSelectChange: 'MDCSelect:change',
    MDCSliderChange: 'MDCSlider:change',
    MDCSliderInput: 'MDCSlider:input',
    MDCSnackbarShow: 'MDCSnackbar:show',
    MDCSnackbarHide: 'MDCSnackbar:hide',
    MDCTabBarChange: 'MDCTabBar:change',
    MDCTabSelected: 'MDCTab:selected',
    MDCTextFieldIcon: 'MDCTextField:icon',
    MDCToolbarChange: 'MDCToolbar:change',
    MDCTopAppBarNav: 'MDCTopAppBar:nav'
  };

  public addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
    const zone: NgZone = this.manager.getZone();
    const eventType: string = this.eventMap[eventName];

    const eventHadler: EventListenerOrEventListenerObject = (event: Event): void => {
      if (event.target !== element) {
        return;
      }

      zone.run((): void => {
        handler(event);
      });
    };

    const addEventHandler: Function = (): void => {
      element.addEventListener(eventType, eventHadler, false);
    };

    const removeEventHandler: Function = (): void => {
      element.removeEventListener(eventType, eventHadler, false);
    };

    zone.runOutsideAngular((): void => {
      addEventHandler();
    });

    return (removeEventHandler);
  }

  public addGlobalEventListener(element: string,
                                eventName: string,
                                handler: Function): Function {
    throw(new Error(`Unsupported event target ${element} for event ${eventName}.`));
  }

  public supports(eventName: string): boolean {
    return this.eventMap.hasOwnProperty(eventName);
  }
}
