import bizrolerights from "./biz-role-rights";

export default {
  ROLE_RIGHTS: bizrolerights,
  AUTHORIZATION_ROLES: {
    ///<summary>No role set</summary>
    NoRole: 0,
    ///<summary>BizAdminRestricted</summary>
    BizAdminRestricted: 1,
    ///<summary>BizAdmin</summary>
    BizAdmin: 2,
    ///<summary>ServiceRestricted</summary>
    ServiceRestricted: 4,
    ///<summary>Service</summary>
    Service: 8,
    ///<summary>InventoryRestricted</summary>
    InventoryRestricted: 16,
    ///<summary>Inventory</summary>
    Inventory: 32,
    ///<summary>Accounting</summary>
    Accounting: 64, //No restricted role, not sure if there is a need
    ///<summary>TechRestricted</summary>
    TechRestricted: 128,
    ///<summary>Tech</summary>
    Tech: 256,
    ///<summary>SubContractorRestricted</summary>
    SubContractorRestricted: 512,
    ///<summary>SubContractor</summary>
    SubContractor: 1024,
    ///<summary>CustomerRestricted</summary>
    CustomerRestricted: 2048,
    ///<summary>Customer</summary>
    Customer: 4096,
    ///<summary>OpsAdminRestricted</summary>
    OpsAdminRestricted: 8192,
    ///<summary>OpsAdmin</summary>
    OpsAdmin: 16384,
    ///<summary>Sales</summary>
    Sales: 32768,
    ///<summary>SalesRestricted</summary>
    SalesRestricted: 65536
  },
  //////////////////////////////////////////////////////////
  // Does current logged in user have role?
  // (Can be an array of roles or a single role, if array returns true if any of the array roles are present for this user)
  //
  hasRole(desiredRole) {
    if (!window.$gz.store.state.roles || window.$gz.store.state.roles === 0) {
      return false;
    }
    //array form?

    if (Array.isArray(desiredRole)) {
      //it's an array of roles, iterate and if any are present then return true
      for (let i = 0; i < desiredRole.length; i++) {
        if ((window.$gz.store.state.roles & desiredRole[i]) != 0) {
          return true;
        }
      }
      return false;
    } else {
      return (window.$gz.store.state.roles & desiredRole) != 0;
    }
  },
  //////////////////////////////////////////////////////////
  // Does current logged in user have *ANY* role?
  //
  //
  hasAnyRole() {
    if (!window.$gz.store.state.roles || window.$gz.store.state.roles === 0) {
      return false;
    }
    return true;
  },
  ///////////////////////////////////////////////////////////////////////
  //  Get a default empty rights object so that it can be present when a
  // form first loads
  //
  defaultRightsObject() {
    return {
      change: false,
      read: false,
      delete: false
    };
  },
  ///////////////////////////////////////////////////////////////////////
  //  Get a default FULL rights object for forms that don't really need
  // to check rights but fits into system for forms in place (e.g. change password)
  //
  fullRightsObject() {
    return {
      change: true,
      read: true,
      delete: true
    };
  },
  ///////////////////////////////////////////////////////////////////////
  //  Get a read only rights object (customer workorder for example)
  //
  readOnlyRightsObject() {
    return {
      change: false,
      read: true,
      delete: false
    };
  },
  /////////////////////////////////
  // aType is the name of the object type as defined in ayatype.js
  //
  getRights(aType) {
    //from bizroles.cs:
    //HOW THIS WORKS / WHATS EXPECTED
    //Change = CREATE, RETRIEVE, UPDATE, DELETE - Full rights
    //
    //ReadFullRecord = You can read *all* the fields of the record, but can't modify it. Change is automatically checked for so only add different roles from change
    //PICKLIST NOTE: this does not control getting a list of names for selection which is role independent because it's required for so much indirectly
    //DELETE = SAME AS CHANGE FOR NOW (There is no specific delete right for now though it's checked for by routes in Authorized.cs in case we want to add it in future as a separate right from create.)
    //NOTE: biz rules can supersede this, this is just for general rights purposes, if an object has restrictive business rules they will take precedence  every time.

    const ret = this.defaultRightsObject();

    //Get the type name from the type enum value
    let typeName = undefined;
    for (const [key, value] of Object.entries(window.$gz.type)) {
      if (value == aType) {
        typeName = key;
        break;
      }
    }

    //Get the AyaNova stock REQUIRED role rights for that object
    const objectRoleRights = this.ROLE_RIGHTS[typeName];
    if (!objectRoleRights) {
      throw new Error(
        `authorizationroles::getRights type ${aType} not found in roles collection`
      );
    }

    //get the logged in user's role
    const userRole = window.$gz.store.state.roles;
    //calculate the effective rights
    //a non zero result of the bitwise calculation means true and zero means false so using !! to force it into a boolean value
    //(contrary to some style guides that say !! is obscure but I say it saves a lot of typing)

    const canChange = !!(userRole & objectRoleRights.Change);

    //sometimes rights to read are false if change is true since change trumps read anyway so accordingly:
    let canReadFullRecord = canChange;
    if (!canReadFullRecord) {
      //can't change but might have special rights to full record:
      canReadFullRecord = !!(userRole & objectRoleRights.ReadFullRecord);
    }

    ret.change = canChange;
    ret.delete = ret.change; //FOR NOW
    ret.read = canReadFullRecord;

    // console.log("authorizationroles::canOpen", {
    //   typeName: typeName,
    //   userRole: userRole,
    //   objectRoleRights: objectRoleRights,
    //   retResultIs: ret
    // });

    return ret;
  },
  /////////////////////////////////
  // convenience method for forms that deal with multiple object types
  // (i.e. grids, history etc, initialization of main menu etc)
  //
  canOpen(aType) {
    const r = this.getRights(aType);
    //convention is change might be defined but not read so canOpen is true eitehr way
    return r.change == true || r.read == true;
  },
  /////////////////////////////////
  // convenience method for forms that deal with multiple object types
  // (i.e. grids, history etc, initialization of main menu etc)
  //
  canChange(aType) {
    const r = this.getRights(aType);
    return r.change == true;
  }
};
