import { injectContext } from '@dvn/core/global/context';
import { ViewPlacement } from '@dvn/core/models/app-config';
import { doesMembershipNeedAgreementConsent, doesMembershipNeedDataCompletion, isMembershipActive } from '@dvn/core/models/membership';
import { buildRoute, getRouteParams } from '@dvn/core/util/route';
import { validateViewParameters } from '@dvn/core/util/view';
import { Component, Element, h, Listen, Prop, State, Watch } from '@stencil/core';
import { getWrapper, wrapBase } from './wrappers';
function getViewComponentName(view) {
  return `dvn-app-view-${view.type}`;
}
export class DvnApp {
  constructor() {
    // TODO Pop this when naviated back. Do we really need to keep navigation stack?
    this.navigationStack = [];
    this.getLogger = () => this.logger.new('DvnApp').setColor('turquoise');
    this.getRouteParams = () => getRouteParams(this.path);
    this.getParamsForView = (view) => {
      if (!view) {
        // there may not be a view for special views such as 'activate'
        return {};
      }
      const paramKeys = Object.keys(view.params || {});
      const params = {};
      const navigationAction = this.navigationStack.find(action => action.viewId === view._id);
      if (navigationAction) {
        paramKeys.forEach(paramKey => {
          params[paramKey] = view.params[paramKey].value || navigationAction.params[paramKey];
        });
      }
      else {
        paramKeys.forEach(paramKey => {
          params[paramKey] = view.params[paramKey].value;
        });
      }
      return params;
    };
    this.dismissSideModal = () => {
      this.sideModalActionData = undefined;
      this.removeLastNavigationItem();
    };
    this.dismissDialog = () => {
      this.dialogActionData = undefined;
      this.removeLastNavigationItem();
    };
  }
  onAction(event) {
    const action = event.detail;
    const { navigationStack } = this;
    const { spaceId, membershipConfigId, membershipId } = this.getRouteParams();
    if (action.type === 'navigation') {
      const navigateAction = action;
      if (navigateAction.direction === 'back') {
        const navigationStack = [...this.navigationStack];
        const lastNavigation = navigationStack.pop();
        if (lastNavigation.placement === ViewPlacement.Dialog) {
          this.dismissDialog();
        }
        else if (lastNavigation.placement === ViewPlacement.SideModal) {
          this.dismissSideModal();
        }
        else {
          this.navigationStack = navigationStack;
        }
        return;
      }
      else if (navigateAction.direction === 'forward') {
        const navigateForwardAction = action;
        if (navigateForwardAction.placement === ViewPlacement.SideModal) {
          this.sideModalActionData = navigateForwardAction;
        }
        else if (navigateForwardAction.placement === ViewPlacement.Dialog) {
          this.dialogActionData = navigateForwardAction;
        }
        else {
          const route = navigateForwardAction.url || buildRoute(spaceId, membershipConfigId, membershipId, navigateForwardAction.viewId);
          this.navigate({ path: route });
        }
        this.navigationStack = [
          // remove old navigation to avoid conflict when searching params with view id
          ...navigationStack.filter(a => a.viewId !== navigateForwardAction.viewId),
          action,
        ];
      }
    }
  }
  ;
  onInvalidation(event) {
    var _a;
    (_a = this.el.querySelector(`#${event.detail.targetViewId}`)) === null || _a === void 0 ? void 0 : _a.invalidate(event);
  }
  ;
  onMembershipChange() {
    this.checkMembershipAndView();
  }
  onAppConfigChange() {
    this.checkMembershipAndView();
  }
  checkMembershipAndView() {
    const { appConfig, membership, memberships } = this;
    const { membershipId, viewId } = this.getRouteParams();
    const logger = this.getLogger();
    if (membershipId && (membership === null || membership === void 0 ? void 0 : membership._id) && membershipId !== (membership === null || membership === void 0 ? void 0 : membership._id)) {
      // app is changed from the left menu. dvn-app-context-injector is going to load the new app.
      logger.debug('doing nothing because dvn-app-context-injector is going to load the new app');
      return;
    }
    if (!membershipId && (memberships === null || memberships === void 0 ? void 0 : memberships.length) > 0) {
      // forward user to /space/membership/home
      logger.debug('forwarding to the first membership home view');
      this.navigate({ path: buildRoute(membership.config.space._id, membership.config._id, membership._id, appConfig.getHomeView()._id) });
      return;
    }
    if (!viewId && membership && (appConfig === null || appConfig === void 0 ? void 0 : appConfig.mainNavigation.items.length) > 0) {
      // forward user to the first view in the main navigation as home page
      logger.debug('forwarding to membership home view');
      this.navigate({ path: buildRoute(appConfig.space._id, membership.config._id, membership._id, appConfig.getHomeView()._id) });
      return;
    }
  }
  removeLastNavigationItem() {
    const navigationStack = [...this.navigationStack];
    navigationStack.pop();
    this.navigationStack = navigationStack;
  }
  getSideModalViewDetails() {
    let SideModalViewTag;
    let sideModalView;
    if (this.sideModalActionData) {
      const navigateForwardAction = this.sideModalActionData;
      sideModalView = this.appConfig.getView(navigateForwardAction.viewId);
      if (sideModalView) {
        SideModalViewTag = getViewComponentName(sideModalView);
      }
    }
    const params = this.getParamsForView(sideModalView);
    if (!validateViewParameters(sideModalView === null || sideModalView === void 0 ? void 0 : sideModalView.params, params)) {
      const logger = this.getLogger();
      logger.errorGroup('invalid view params for side modal', {
        viewId: sideModalView._id,
        viewConfigParams: sideModalView === null || sideModalView === void 0 ? void 0 : sideModalView.params,
        givenParams: params,
      });
      return { SideModalViewTag: 'dvn-missing-parameters', sideModalView };
    }
    return { SideModalViewTag, sideModalView };
  }
  getDialogViewDetails() {
    let DialogViewTag;
    let dialogView;
    if (this.dialogActionData) {
      const navigateForwardAction = this.dialogActionData;
      dialogView = this.appConfig.getView(navigateForwardAction.viewId);
      if (dialogView) {
        DialogViewTag = getViewComponentName(dialogView);
      }
      else {
        console.warn(`View '${navigateForwardAction.viewId}' is not found.`);
      }
    }
    return { DialogViewTag, dialogView };
  }
  render() {
    const { appConfig, membership, memberships, notifier, user } = this;
    const { viewId } = this.getRouteParams();
    const logger = this.getLogger();
    const logData = {
      membership,
      navigate: this.navigate,
      notifier,
      user,
      path: this.path,
      viewId,
    };
    const context = {
      apiAtama: this.apiAtama,
      apiData: this.apiData,
      apiTakvim: this.apiTakvim,
      apiUye: this.apiUye,
      appContextInvalidator: this.appContextInvalidator,
      logger,
      membership,
      navigate: this.navigate,
      notifier,
      user
    };
    if (!appConfig) {
      logger.debugGroup('context is being loaded', logData);
      // context is being loaded
      return wrapBase(h("div", { class: "d-flex justify-content-center" },
        h("dvn-progress", { indefinite: true })));
    }
    const wrapper = getWrapper(this.navigate, this.storage, this.theme, this.apiKimlik, appConfig, user, memberships, membership, viewId);
    let Tag;
    if (!membership) {
      if (memberships.length > 0) {
        // if there are memberships but no membership, then the user is viewing another membership
        return wrapper(h("dvn-not-found", null));
      }
      // user has no membership
      return wrapper(h("dvn-app-not-member-of-any", null));
    }
    else {
      if (!isMembershipActive(membership)) { // make user activate the membership
        Tag = 'dvn-app-activate-membership';
      }
      else if (doesMembershipNeedAgreementConsent(membership)) { // make user accept the agreements
        Tag = 'dvn-app-membership-consent';
      }
      else if (doesMembershipNeedDataCompletion(membership)) { // make user fill all the required fields defined in the membership
        Tag = 'dvn-member-info-required';
      }
    }
    let viewConfig;
    if (!Tag) {
      viewConfig = appConfig.getView(viewId);
      if (viewConfig) {
        Tag = getViewComponentName(viewConfig);
      }
    }
    const { SideModalViewTag, sideModalView } = this.getSideModalViewDetails();
    const { DialogViewTag, dialogView } = this.getDialogViewDetails();
    if (Tag) {
      const params = this.getParamsForView(viewConfig);
      if (!validateViewParameters(viewConfig === null || viewConfig === void 0 ? void 0 : viewConfig.params, params)) {
        logger.errorGroup('invalid view params', {
          viewId,
          viewConfigParams: viewConfig === null || viewConfig === void 0 ? void 0 : viewConfig.params,
          givenParams: params,
        });
        return wrapper(h("dvn-missing-parameters", null));
      }
      const viewToDisplay = h("div", null,
        h(Tag, Object.assign({}, context, { key: viewId, id: viewId, params: params, view: viewConfig })),
        SideModalViewTag &&
          h("dvn-side-modal", { onDismiss: this.dismissSideModal },
            h(SideModalViewTag, Object.assign({}, context, { key: sideModalView._id, id: sideModalView._id, params: this.getParamsForView(sideModalView), view: sideModalView }))),
        DialogViewTag &&
          h("dvn-dialog", { raw: true, shown: true, onDismiss: this.dismissDialog },
            h(DialogViewTag, Object.assign({}, context, { key: dialogView._id, id: dialogView._id, params: this.getParamsForView(dialogView), view: dialogView }))));
      return wrapper(viewToDisplay);
    }
    if (this.path === '/') {
      // user will be forwarded to the home view id
      return null;
    }
    this.logger.new('DvnApp').setColor('turquoise').debugGroup('view not found', { viewId, path: this.path });
    return wrapper(h("dvn-not-found", null));
  }
  static get is() { return "dvn-app"; }
  static get originalStyleUrls() { return {
    "$": ["dvn-app.css"]
  }; }
  static get styleUrls() { return {
    "$": ["dvn-app.css"]
  }; }
  static get properties() { return {
    "apiAtama": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "AtamaApi",
        "resolved": "AtamaApi",
        "references": {
          "AtamaApi": {
            "location": "import",
            "path": "../../../../atama/src/api/atamaApi"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "apiData": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "DataApi",
        "resolved": "DataApi",
        "references": {
          "DataApi": {
            "location": "import",
            "path": "@dvn/core/api"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "apiKimlik": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "KimlikApi",
        "resolved": "KimlikApi",
        "references": {
          "KimlikApi": {
            "location": "import",
            "path": "@dvn/kimlik/api/kimlikApi"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "apiTakvim": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "TakvimApi",
        "resolved": "TakvimApi",
        "references": {
          "TakvimApi": {
            "location": "import",
            "path": "../../../../takvim/api/takvimApi"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "apiUye": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "UyeApi",
        "resolved": "UyeApi",
        "references": {
          "UyeApi": {
            "location": "import",
            "path": "@dvn/uye/api"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "appConfig": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "AppConfig",
        "resolved": "AppConfig",
        "references": {
          "AppConfig": {
            "location": "import",
            "path": "@dvn/core/models/app-config"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "logger": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Logger",
        "resolved": "Logger",
        "references": {
          "Logger": {
            "location": "import",
            "path": "@dvn/core/log/logger"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "theme": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "AlacaTheme",
        "resolved": "AlacaTheme",
        "references": {
          "AlacaTheme": {
            "location": "import",
            "path": "@dvn/alaca/theme"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "navigate": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "NavigationHandler",
        "resolved": "(config: NavigateConfig) => void",
        "references": {
          "NavigationHandler": {
            "location": "import",
            "path": "@dvn/core/routing/routing"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "storage": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Storage",
        "resolved": "Storage",
        "references": {
          "Storage": {
            "location": "import",
            "path": "@dvn/kimlik/storage/Storage.interface"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "path": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "path",
      "reflect": false
    },
    "appContextInvalidator": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "AppContextInvalidator",
        "resolved": "() => void",
        "references": {
          "AppContextInvalidator": {
            "location": "import",
            "path": "@dvn/core/global/context/context"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "membership": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Membership",
        "resolved": "Membership",
        "references": {
          "Membership": {
            "location": "import",
            "path": "@dvn/core/models/membership"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "memberships": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Membership[]",
        "resolved": "Membership[]",
        "references": {
          "Membership": {
            "location": "import",
            "path": "@dvn/core/models/membership"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "notifier": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Notifier",
        "resolved": "Notifier",
        "references": {
          "Notifier": {
            "location": "import",
            "path": "@dvn/alaca/global/notifier/models"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "user": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "User",
        "resolved": "User",
        "references": {
          "User": {
            "location": "import",
            "path": "@dvn/kimlik/api/models"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    }
  }; }
  static get states() { return {
    "navigationStack": {},
    "dialogActionData": {},
    "sideModalActionData": {}
  }; }
  static get elementRef() { return "el"; }
  static get watchers() { return [{
      "propName": "membership",
      "methodName": "onMembershipChange"
    }, {
      "propName": "appConfig",
      "methodName": "onAppConfigChange"
    }]; }
  static get listeners() { return [{
      "name": "action",
      "method": "onAction",
      "target": undefined,
      "capture": false,
      "passive": false
    }, {
      "name": "invalidation",
      "method": "onInvalidation",
      "target": undefined,
      "capture": false,
      "passive": false
    }]; }
}
injectContext(DvnApp);
