import { PLATFORM } from 'aurelia-framework';
import { Actions, EntityTypeNames, RolesMode, SecurityRouteGroup } from './../../constants/constants';
import { Various } from './../../model/common-model';
import { ExtendedRouteConfig, RouteSettings } from './../../config';

interface SecurityRouteConfig {
  routePrefix: string;
  after?: string;
  before?: string;
}
interface RolesRouteConfig extends SecurityRouteConfig {
  group: string;
  userRouteName: string;
  detailTitle?: string;
  listTitle?: string;
  detailModuleId?: string;
  listModuleId?: string;
};
interface UsersRouteConfig extends SecurityRouteConfig, RouteSettings {
  list: {
    moduleId?: string;
    settings?: RouteSettings;
    title?: string;
  };
  detail: {
    moduleId?: string;
    settings?: RouteSettings;
    title?: string;
  };
};

function findInsertionIndex(routes: ExtendedRouteConfig[], search: string) {
  return routes.findIndex(x => x.route == search || x.moduleId == search || x.name == search || x.href == search);
}
function insertRoutes(routes: ExtendedRouteConfig[], newRoutes: ExtendedRouteConfig[], config: Partial<SecurityRouteConfig>) {
  let index: number = -1;
  if (config.after) {
    index = findInsertionIndex(routes, config.after);
    if (index >= 0) {
      index++; // Insert after
    }
  }
  if (config.before && index < 0) {
    index = findInsertionIndex(routes, config.before);
  }
  routes.splice(index, 0, ...newRoutes);
  return routes;
}

export function addRolesToRoutes(routes: ExtendedRouteConfig[], inputConfig: Partial<RolesRouteConfig> = {}, srcPrefix: string = 'digiwall-lib') {
  let config: RolesRouteConfig = { group: SecurityRouteGroup, routePrefix: 'roles', after: 'users', userRouteName: 'users', detailTitle: 'common:role.role', listTitle: 'common:role.roles', detailModuleId: PLATFORM.moduleName(srcPrefix + '/vm/security/roles/role-detail'), listModuleId: PLATFORM.moduleName(srcPrefix + '/vm/security/roles/role-list') };
  Object.assign(config, inputConfig);

  let userRoute = routes.find(x => x.name == config.userRouteName);

  let newRoutes: ExtendedRouteConfig[] = [
    {
      route: `${config.routePrefix}/:param1`, name: 'roles-detail', moduleId: config.detailModuleId,
      title: config.detailTitle, nav: false, settings: { resource: EntityTypeNames.Role, action: Actions.Read, params: { userResource: userRoute?.settings?.resource } }, href: `${config.routePrefix}/${Various.NewId}`
    },
    {
      route: `${config.routePrefix}/all`, name: 'roles', moduleId: config.listModuleId,
      title: config.listTitle, nav: true, settings: { group: config.group, resource: EntityTypeNames.Role, action: Actions.Read }, href: `${config.routePrefix}/all`
    },
  ];
  return insertRoutes(routes, newRoutes, config);
};

export function addUsersToRoutes(routes: ExtendedRouteConfig[], config: Partial<UsersRouteConfig> = {},
  rolesMode: RolesMode = 'none', srcPrefix: string = 'digiwall-lib', addDetailRoute = true) {

  let commonSettings: RouteSettings = { group: SecurityRouteGroup, resource: EntityTypeNames.User };

  config.routePrefix ??= 'users';
  config.list ??= {};
  config.list.moduleId ??= PLATFORM.moduleName(srcPrefix + '/vm/security/users/user-list');
  config.list.title ??= 'common:user.users';

  config.detail ??= {};
  config.detail.moduleId ??= PLATFORM.moduleName(srcPrefix + `/vm/security/users/user-detail-${rolesMode}`);
  config.detail.title ??= 'common:user.user';

  let newRoutes: ExtendedRouteConfig[] = [
    {
      route: `${config.routePrefix}/all`, name: 'users', moduleId: config.list.moduleId,
      title: config.list.title, nav: true, settings: Object.assign({}, commonSettings, config, config.list?.settings || { action: Actions.Read }),
      href: `${config.routePrefix}/all`
    }
  ];

  if (addDetailRoute) {
    newRoutes.push({
      route: `${config.routePrefix}/:param1`, name: 'users-detail', moduleId: config.detail.moduleId,
      title: config.detail.title, nav: false, settings: Object.assign({}, commonSettings, config, config.detail?.settings || { action: Actions.Read }),
      href: `${config.routePrefix}/${Various.NewId}`
    });
  }

  return insertRoutes(routes, newRoutes, config);
};

export interface PermissionsConfig {
  perContext?: {
    context?: string,
    routeName?: string,
    qualifiedName: string[],
    href?: string,
    isCrud?: boolean,
    hint?: string,
    forceType?: 'screen' | 'functionality' | null,
  }[];
  permissionNames?: { [key: string]: { [key: string]: string } };
}

export function applyDefaultPermissionsConfig(config?: PermissionsConfig): PermissionsConfig {
  config ??= {};
  config.perContext ??= [];
  config.perContext.push(...[
    { context: 'agGridViewPublic', qualifiedName: ['common:aggridview.system'], isCrud: false },
    { context: 'agGridView', qualifiedName: ['common:aggridview.system'], isCrud: false }
  ]);
  config.permissionNames = Object.assign({
    'ag-grid-view-public': {
      [Actions.Create]: 'common:aggridview.agGridViewPublic'
    },
    'ag-grid-view': {
      [Actions.Read]: 'common:aggridview.agGridView'
    }
  }, config.permissionNames ?? {});
  return config;
};