import { Component, OnDestroy, OnInit } from '@angular/core';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import { base64 } from 'rfc4648';
import { GeneralConfirmDialogComponent } from 'src/app/shared/dialogs/general-confirm-dialog/general-confirm-dialog.component';
import { AccountAvatarRecord } from 'src/app/shared/server-services/query-records/account-records';
import { DialogueRecord } from 'src/app/shared/server-services/query-records/room-records';
import { ResourceType } from 'src/app/shared/server-services/query-records/sidebar-records';
import { RouterResponse } from 'src/app/shared/services/router-handler.service';
import { HeaderComponent } from '../header.component';

export enum Pages {
  HOME = '',
  SEARCH = 'search',
  DIALOGUE = 'private',
  ROOM = 'room',
  ROOM_DETAILS = 'details',
  DRIVE = 'drive',
  MAIN_MENU = 'main-menu',
  ACCOUNT_SETTINGS = 'account',
  CONTACTS = 'contact-list',
  LICENSES = 'licenses',
  LICENSE_BUY = 'license-buy',
  NANO_METRICS = 'nano-metrics',
  NANO_MANAGER = 'nano-manager',
  SETTINGS = 'settings',
  REJECTED_ROOMS = 'rejected-rooms',
  ADVANCED_SETTINGS = 'advanced-settings',
  SALE_CODE_MANAGER = 'sale-code-manager',
  LOGIN = 'login',
  REGISTER = 'register',
  REGISTER_CONFIRM = 'register-confirm',
  LICENSE_VIEW = 'license-view',
  ACCOUNT_RECOVERY = 'account-recovery',
  ACCOUNT_RECOVERY_CONFIRM = 'account-recovery-confirm',
  TIMED_OFFERS = 'offers',
  ABOUT = 'about',
  SESSION_HANDLER = 'session-handler',
}

type HeaderConfigObject = {
  init?: (route: RouterResponse) => Promise<void>;
  showMenuButton?: boolean;
  showSearch?: boolean;
  showPageTitle?: boolean;
  headerTitle?: string;
  showRoomTitle?: boolean;
  roomTitle?: string;
  showDialogueSettings?: boolean;
  showRoomSettings?: boolean;
  newsListVisible?: boolean;
  backNavigation?: (route: RouterResponse) => {
    url: string;
    fragment?: {
      [key: string]: string;
    };
  };
  customBackSwipe?: (route: RouterResponse) => {
    url: string;
    fragment?: {
      [key: string]: string;
    };
  };
};

enum RoomSettingOption {
  HIDE_SEARCH = 'HIDE_SEARCH',
  SEARCH = 'SEARCH',
  MANAGE_ROOM = 'MANAGE_ROOM',
  SHARE_URL = 'SHARE_URL',
  DRIVE = 'DRIVE',
  LEAVE = 'LEAVE',
  DELETE = 'DELETE',
}

const basicTitledView: (
  title: string,
  backPage: string,
  prop?: HeaderConfigObject
) => HeaderConfigObject = (title: string, backPage: string, prop?: Object) => ({
  showPageTitle: true,
  headerTitle: title,

  backNavigation: () => ({ url: backPage }),

  ...prop,
});

@Component({
  selector: 'app-header',
  templateUrl: './header-mobile.component.html',
  styleUrls: ['./header-mobile.component.scss'],
})
export class HeaderMobileComponent extends HeaderComponent implements OnInit, OnDestroy {
  setupRoomHeader = (route: RouterResponse) => {
    let outerPinnedKey;
    if (route.fragment?.roomkey) {
      outerPinnedKey = route.fragment.roomkey;
      try {
        let parsedPinnedKey = base64.parse(outerPinnedKey);
        this.roomService.registerPinnedKey(this.resourceId, outerPinnedKey);
      } catch (e) {
        console.error('can not parse pinned key');
        // just try to load the room without pinned key
        // if it fails, we response with error message
        // there is a chance, we do not need the pinned key
        // when we are logged in and we are member of the room
      }
    }

    this.resourceId = route.params.id;
    this.resourceDataLoaded = false;
    this.resourceLoadError = false;

    return this.roomService
      .getRoom(this.resourceId)
      .then((res) => {
        // pass to the catch handler
        if (!res) throw 'there is no response from get data';

        this.avatar = null;
        this.roomImage = res.data?.avatar;
        this.resourceTitle = res.data?.name;
        this.resourceDataLoaded = true;

        return this.roomService
          .getMyRoomPermissions(route.params.id)
          .then((myPerm) => {
            this.isMemberOfRoom = !!myPerm.account;
            this.isOwnerOfRoom = myPerm.ownerAccountId == this.me.id;
            return;
          })
          .catch((err) => {
            this.isMemberOfRoom = false;
            this.isOwnerOfRoom = false;
            return;
          });
      })
      .catch((err) => {
        console.error('could not load room data', err);
        this.isMemberOfRoom = false;
        this.isOwnerOfRoom = false;
        this.resourceLoadError = true;
        return Promise.resolve();
      });
  };

  setupDialogueHeader = (route) => {
    this.resourceId = route.params.id;
    this.resourceDataLoaded = false;
    this.resourceLoadError = false;

    return this.dialogueService
      .getData(route.params.id)
      .then((dialogueRecord: DialogueRecord) => {
        this.isBlocked = dialogueRecord.hidden;

        this.accountService.getAccount(dialogueRecord.id).then((acc) => {
          this.avatar = acc;
          this.roomImage = null;
          this.resourceTitle = acc.avatarName;
          this.resourceDataLoaded = true;
        });
        return;
      })
      .catch((err) => {
        console.error('could not load dialogue data', err);
        this.resourceLoadError = true;
        return;
      });
  };

  mobileHeaderConfig: { [key in Pages | 'DEFAULT']: HeaderConfigObject } = {
    DEFAULT: {
      showMenuButton: true,
      showSearch: true,
    },
    [Pages.HOME]: {
      showMenuButton: true,
      showSearch: true,
      newsListVisible: true,
      customBackSwipe: () => ({
        url: Pages.HOME,
      }),
    },
    [Pages.SEARCH]: {
      showSearch: true,
      backNavigation: () => ({
        url: Pages.HOME,
      }),
    },
    [Pages.DIALOGUE]: {
      init: this.setupDialogueHeader,
      showRoomTitle: true,
      showDialogueSettings: true,
      newsListVisible: true,
      backNavigation: () => ({
        url: Pages.HOME,
      }),
    },
    [Pages.ROOM]: {
      init: this.setupRoomHeader,
      showRoomTitle: true,
      showRoomSettings: true,
      newsListVisible: true,
      backNavigation: () => ({
        url: Pages.HOME,
      }),
    },
    [Pages.ROOM_DETAILS]: {
      init: this.setupRoomHeader,
      showRoomTitle: true,
      showRoomSettings: true,
      newsListVisible: true,
      backNavigation: (route: RouterResponse) => {
        return { url: '/room/' + route.params.id + '/chat/' + Pages.ROOM };
      },
    },
    [Pages.DRIVE]: {
      init: this.setupRoomHeader,
      showRoomTitle: true,
      showRoomSettings: true,
      newsListVisible: true,
      backNavigation: (route: RouterResponse) => {
        if (route?.fragment?.search) {
          const fragment = { search: route.fragment.search };
          const url = Pages.SEARCH;
          return { url, fragment };
        } else {
          const url = '/room/' + route.params.id + '/chat/' + Pages.ROOM;
          return { url };
        }
      },
    },
    [Pages.MAIN_MENU]: basicTitledView(marker('Main Menu'), Pages.HOME),
    [Pages.ACCOUNT_SETTINGS]: basicTitledView(marker('Account Settings'), '/' + Pages.MAIN_MENU),

    [Pages.CONTACTS]: basicTitledView(marker('Contacts'), '/' + Pages.MAIN_MENU, {
      backNavigation: (route: RouterResponse) => {
        return route.fragment.hasOwnProperty('fromHome')
          ? { url: Pages.HOME }
          : { url: '/' + Pages.MAIN_MENU };
      },
    }),

    [Pages.LICENSES]: basicTitledView(marker('Licenses'), '/' + Pages.MAIN_MENU),
    [Pages.LICENSE_BUY]: basicTitledView(marker('License Purchase'), '/' + Pages.MAIN_MENU),
    [Pages.NANO_METRICS]: basicTitledView(marker('Nano Metrics'), '/' + Pages.MAIN_MENU),
    [Pages.NANO_MANAGER]: basicTitledView(marker('Nano Manager'), '/' + Pages.MAIN_MENU),
    [Pages.SETTINGS]: basicTitledView(marker('Settings'), '/' + Pages.MAIN_MENU),
    [Pages.REJECTED_ROOMS]: basicTitledView(marker('Rejected Rooms'), '/' + Pages.MAIN_MENU),
    [Pages.ADVANCED_SETTINGS]: basicTitledView(marker('Advanced Settings'), '/' + Pages.SETTINGS),
    [Pages.SALE_CODE_MANAGER]: basicTitledView(marker('Sale Codes'), '/' + Pages.MAIN_MENU),
    [Pages.LOGIN]: {
      showPageTitle: true,
      headerTitle: marker('Login'),
      showMenuButton: true,
    },
    [Pages.REGISTER]: basicTitledView(marker('Register'), '/' + Pages.LOGIN),
    [Pages.REGISTER_CONFIRM]: basicTitledView(marker('Register Confirm'), '/' + Pages.LOGIN),
    [Pages.LICENSE_VIEW]: basicTitledView(marker('License types'), '/' + Pages.MAIN_MENU),
    [Pages.ACCOUNT_RECOVERY]: basicTitledView(marker('Account Recovery'), '/' + Pages.LOGIN),
    [Pages.ACCOUNT_RECOVERY_CONFIRM]: basicTitledView(
      marker('Account Recovery Confirm'),
      '/' + Pages.LOGIN
    ),
    [Pages.TIMED_OFFERS]: basicTitledView(marker('Timed Offers'), '/' + Pages.MAIN_MENU),
    [Pages.ABOUT]: basicTitledView(marker('About'), '/' + Pages.SETTINGS),
    [Pages.SESSION_HANDLER]: basicTitledView(
      marker('Session Handler'),
      '/' + Pages.ACCOUNT_SETTINGS
    ),
  };

  public actualHeaderConfig: HeaderConfigObject = {};

  /** Room menu bar visiblity */
  public isRoomMenuOpen = false;

  public resourceDataLoaded = false;
  public resourceLoadError = false;

  public roomImage: ArrayBuffer;
  public resourceTitle: string;
  public avatar: AccountAvatarRecord;

  public isBlocked = false;
  private resourceId: string;

  public isOwnerOfRoom: boolean = false;
  public isMemberOfRoom: boolean = false;

  public roomSettingOption: typeof RoomSettingOption = RoomSettingOption;

  ngOnInit(): void {
    super.ngOnInit();
    this.routerHandler.subscribeAll(this.updateHeaderContent);

    this.subscriptionService.subscribeWorkspaceLoaded(() => {
      const route = this.routerHandler.getRoute();
      this.updateHeaderContent(route);
    });

    this.swipeService.initBackNavigation(() => {
      console.log('navigating back from swipe');
      this.swipeBack();
    });
  }

  ngOnDestroy(): void {
    super.ngOnDestroy();
    this.routerHandler.unsubscribeAll(this.updateHeaderContent);
  }

  private swipeBack = () => {
    if (this.actualHeaderConfig?.customBackSwipe) {
      const route = this.routerHandler.getRoute();
      const { url = Pages.HOME, fragment = null } = this.actualHeaderConfig?.customBackSwipe(route);

      if (url) {
        if (fragment) {
          const rawFragment = this.routerHandler.fragmentToRaw(fragment);
          this.routerHandler.navigate([url], { fragment: rawFragment });
        } else {
          this.routerHandler.navigate([url]);
        }
      }
    } else {
      this.back();
    }
  };

  setHeader(config) {
    this.actualHeaderConfig = { ...config };
  }

  private headerConfigInitStarted: HeaderConfigObject;
  private updateHeaderContent = (route) => {
    this.recalculateBadge();

    let splitUrl = route.url.split('/');
    let page = splitUrl?.[splitUrl.length - 1];
    if (page in this.mobileHeaderConfig) {
      let currConf: HeaderConfigObject = this.mobileHeaderConfig[page];
      this.headerConfigInitStarted = currConf;

      if (currConf.init) {
        currConf.init(route).then(() => {
          if (this.headerConfigInitStarted == currConf) {
            this.setHeader(currConf);
          } // else this promise was too slow, the user changed the header
        });
      } else {
        this.setHeader(currConf);
      }
    } else {
      console.warn(`Header state is missing (${page})`);
      this.setHeader(this.mobileHeaderConfig.DEFAULT);
    }

    return 0;
  };

  public handleRoomClick = (event) => {
    event.preventDefault();
    const route: RouterResponse = this.routerHandler.getRoute();
    const routeType: Pages = <Pages>route.url.split('/').pop();

    if ([Pages.ROOM_DETAILS, Pages.DRIVE].includes(routeType)) {
      const url = `room/${route?.params?.id}/chat/${Pages.ROOM}`;
      this.routerHandler.navigate([url]);
    }
  };

  public blockUser() {
    this.dialogService
      .openConfirmDialog(marker('Block user'), marker('Are you sure you want to block this user?'))
      .subscribe((confirmed) => {
        if (!confirmed) return;

        this.accountService.blockUser(this.resourceId).then(() => {
          this.snackbarService.showSnackbar(marker('User blocked.'));
          this.isBlocked = true;
        });
      });
  }

  public unblockUser() {
    this.accountService.unblockUser(this.resourceId).then(() => {
      this.snackbarService.showSnackbar(marker('User unblocked.'));
      this.isBlocked = false;
    });
  }

  public back() {
    if (!this.actualHeaderConfig.backNavigation) {
      console.warn(
        'Missing backNavigation property on actualHeaderConfig. Calling histry.back() instead'
      );
      history.back();
      return;
    }

    const route = this.routerHandler.getRoute();
    const { url = Pages.HOME, fragment = null } = this.actualHeaderConfig.backNavigation(route);

    if (fragment) {
      const rawFragment = this.routerHandler.fragmentToRaw(fragment);
      this.routerHandler.navigate([url], { fragment: rawFragment });
    } else {
      this.routerHandler.navigate([url]);
    }
  }

  public toggleRoomMenu() {
    this.isRoomMenuOpen = this.isRoomMenuOpen ? false : true;
  }

  public handleRoomSettingClick = (option: string) => {
    if (option in RoomSettingOption) {
      switch (option) {
        case RoomSettingOption.HIDE_SEARCH:
          this.actualHeaderConfig.showSearch = false;
          this.actualHeaderConfig.showRoomTitle = true;
          break;
        case RoomSettingOption.SEARCH:
          this.actualHeaderConfig.showSearch = true;
          this.actualHeaderConfig.showRoomTitle = false;
          break;
        case RoomSettingOption.MANAGE_ROOM:
          this.routerHandler.navigate(['/room/' + this.resourceId + '/' + Pages.ROOM_DETAILS], {
            fragment: this.routerHandler.getRoute().rawFragment,
          });
          break;
        case RoomSettingOption.SHARE_URL:
          this.copyPublicShareUrl();
          break;
        case RoomSettingOption.DRIVE:
          this.routerHandler.navigate(['/room/' + this.resourceId + '/' + Pages.DRIVE], {
            fragment: this.routerHandler.getRoute().rawFragment,
          });
          break;
        case RoomSettingOption.LEAVE:
          var ref = this.dialog.open(GeneralConfirmDialogComponent, {
            data: {
              title: this.resourceTitle,
              text: marker('Are you sure you want to leave?'),
            },
          });

          ref.afterClosed().subscribe((closedWithOK: boolean) => {
            if (closedWithOK) {
              this.roomService.leaveRoom(this.resourceId).then((res) => {
                this.routerHandler.navigate(['/']);
              });
            }
          });
          break;
        case RoomSettingOption.DELETE:
          var ref = this.dialog.open(GeneralConfirmDialogComponent, {
            data: {
              title: this.resourceTitle,
              text: marker('Are you sure you want to delete this room?'),
            },
          });

          ref.afterClosed().subscribe((closedWithOK: boolean) => {
            if (closedWithOK) {
              this.roomService.deleteRoom(this.resourceId).then((res) => {
                this.routerHandler.navigate(['/']);
              });
            }
          });
          break;
      }
    } else {
      console.warn('handleRoomSettingClick param mismatch');
    }
  };

  copyPublicShareUrl() {
    this.roomService.getPublicShareUrl(this.resourceId).then((r) => {
      this.clipboardService
        .copy(r)
        .then(() => {
          this.snackbarService.showSnackbar(marker('Url copied to clipboard'));
        })
        .catch((err) => {
          console.error('clipboard err', err);
          this.dialogService.openAlertDialog(
            marker('Copy Error'),
            marker('Could not copy to the clipboard')
          );
        });
    });
  }
}
