"use strict";

var READONLY_INVENTORY_ROLES = require('../constant/chemical/readonly-roles-inventory.constant');
var ROLES = require('../constant/core/roles.constant');
var _require = require('../constant/relationship/label.constant'),
  EDGE = _require.EDGE,
  EDGE_TYPE = _require.EDGE_TYPE,
  GLOBAL = _require.NODE.GLOBAL;
var AnalyticsHelper = require('./analytics.helper');
var RelationshipHelper = require('./relationship.helper');
module.exports.permissionError = function (message) {
  return Object.assign(new Error(message || 'no permission'), {
    status: 403
  });
};
module.exports.hasRole = function (user, role) {
  var criteria = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  return user.roles && user.roles.some(function (r) {
    return r.role === role && (criteria.tenantCode && criteria.tenantCode !== 'ALL' && r.tenantCode !== 'ALL' ? r.tenantCode === criteria.tenantCode : true) && (criteria.campusCode && criteria.campusCode !== 'ALL' && r.campusCode !== 'ALL' ? r.campusCode === criteria.campusCode : true) && (criteria.types ? criteria.types.some(function (type) {
      return r.type && r.type === type;
    }) : true);
  });
};
module.exports.hasRelationship = function (user, relationship) {
  var criteria = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var hasRelation = Array.isArray(user.relationships) && user.relationships.some(function (r) {
    return r.edge.label === relationship;
  });
  if (criteria.campusCode) {
    hasRelation = hasRelation && RelationshipHelper.hasRelationshipWithRole(criteria.campusCode, user.relationships, relationship);
  }
  if (criteria.inventoryId) {
    hasRelation = hasRelation && RelationshipHelper.hasRelationshipWithRole(criteria.inventoryId, user.relationships, relationship);
  }
  if (criteria.groups) {
    hasRelation = hasRelation && criteria.groups.some(function (groupId) {
      return RelationshipHelper.hasRelationshipWithRole(groupId, user.relationships, relationship);
    });
  }
  if (criteria.tenantCode) {
    hasRelation = hasRelation && RelationshipHelper.hasRelationshipWithRole(criteria.tenantCode, user.relationships, relationship);
  }
  return hasRelation;
};
module.exports.isAnalyticsAdmin = function (_ref, isNeptune) {
  var relationships = _ref.relationships;
  return (
    //  # TODO: modify after mongo => neptune migration
    relationships && isNeptune && relationships.some(function (_ref2) {
      var _ref2$edge = _ref2.edge,
        label = _ref2$edge.label,
        type = _ref2$edge.type;
      return type === EDGE_TYPE.ROLE && label === EDGE.ANALYTICS_ADMIN;
    }) || relationships && relationships.some(function (_ref3) {
      var role = _ref3.role;
      return role === EDGE.ANALYTICS_ADMIN;
    })
  );
};
module.exports.isClientAdmin = function (user) {
  return RelationshipHelper.hasRelationshipWithRole(GLOBAL, user.relationships, EDGE.CLIENT_ADMIN);
};
module.exports.isInventorySpecialist = function (campusCode, user) {
  return module.exports.hasRelationship(user, EDGE.INVENTORY_SPECIALIST, {
    campusCode: campusCode
  });
};
module.exports.isChemAdmin = function (campusCode, user) {
  return module.exports.hasRole(user, ROLES.CHEMICAL_ADMIN, {
    campusCode: campusCode
  }) || module.exports.hasRelationship(user, EDGE.CHEMICAL_ADMIN, {
    campusCode: campusCode
  });
};
module.exports.isChemAdminReadOnly = function (campusCode, user) {
  return module.exports.hasRole(user, ROLES.CHEMICAL_ADMIN_READ_ONLY, {
    campusCode: campusCode
  }) || module.exports.hasRelationship(user, EDGE.CHEMICAL_ADMIN_READ_ONLY, {
    campusCode: campusCode
  });
};
module.exports.isChemInfo = function (user) {
  return module.exports.hasRole(user, ROLES.CHEMICAL_INFORMATICS) || module.exports.hasRelationship(user, EDGE.CHEM_INFO);
};
module.exports.hasChemAdminRead = function (campusCode, user) {
  return module.exports.isChemAdminReadOnly(campusCode, user) || module.exports.isChemAdmin(campusCode, user);
};
module.exports.isEHSAdmin = function (campusCode, user) {
  return module.exports.hasRole(user, ROLES.EHS_ADMIN, {
    campusCode: campusCode
  }) || module.exports.hasRelationship(user, EDGE.EHS_DEPARTMENT_ADMIN, {
    campusCode: campusCode
  });
};
module.exports.isControlAreaAdmin = function (user, campusCode) {
  return RelationshipHelper.hasRelationshipWithRole(campusCode, user.relationships, EDGE.CONTROL_AREA_ADMIN);
};
module.exports.isSystemControlAreaAdmin = function (user, tenantCode) {
  return RelationshipHelper.hasRelationshipWithRole(tenantCode, user.relationships, EDGE.SYSTEM_CONTROL_AREA_ADMIN);
};
module.exports.hasRoleWithReadAccessToInventory = function (inventory, user) {
  var inventoryGroupIds = inventory.groups.map(function (group) {
    return group.id;
  });
  return !module.exports.isMemberOrColleagueOfInventory(inventory, user) && user.roles.filter(function (role) {
    return READONLY_INVENTORY_ROLES.includes(role.role);
  }).reduce(function (acc, curr) {
    return acc.concat(curr.groupIds);
  }, []).some(function (groupId) {
    return inventoryGroupIds.includes(groupId);
  }) || module.exports.hasChemAdminRead(inventory.campusCode, user) || user.relationships && user.relationships.some(function (r) {
    return READONLY_INVENTORY_ROLES.includes(r.role) && inventoryGroupIds.includes(r.nodeId);
  });
};
module.exports.isMemberOfInventory = function (inventory, user) {
  return module.exports.hasManageAccessToInventory(inventory, user) || user.groups.some(function (group) {
    return inventory.groups.map(function (item) {
      return item.id;
    }).includes(group.id);
  }) || module.exports.hasRelationship(user, EDGE.MEMBER, {
    inventoryId: inventory._id.toString()
  });
};
module.exports.isMemberOrColleagueOfInventory = function (inventory, user) {
  return module.exports.isMemberOfInventory(inventory, user) || !!(inventory.colleagues || []).find(function (colleague) {
    return user.inventories && user.inventories.some(function (inv) {
      return colleague.id ? inv._id.toString() === colleague.id.toString() : inv._id.toString() === colleague._id.toString();
    });
  });
};
module.exports.hasManageAccessToInventory = function (inventory, user) {
  if (inventory && user) {
    return module.exports.isChemAdmin(inventory.campusCode, user) || module.exports.isManagerOfInventory(inventory, user) || module.exports.isGroupOwner(inventory, user) || module.exports.isGroupDelegate(inventory, user) || module.exports.isInventorySpecialist(inventory, user);
  }
  return false;
};
module.exports.isManagerOfInventory = function (inventory, user) {
  return (inventory.owner || {}).userId === user.userId || (inventory.permissions || []).find(function (p) {
    return p.type === 'MANAGE' && p.userId === user.userId;
  }) || user.relationships.some(function (relationship) {
    return relationship.edge.label === 'OWNER' && relationship.node.id === inventory._id;
  });
};
module.exports.isGroupOwner = function (inventory, user) {
  return (inventory.groups || []).some(function (group) {
    return (group.owner || {}).userId === user.userId;
  }) || module.exports.hasRelationship(user, EDGE.OWNER, {
    groups: inventory.groups.map(function (g) {
      return g.id;
    })
  });
};
module.exports.isGroupDelegate = function (inventory, user) {
  var inventoryGroupIds = inventory.groups.map(function (group) {
    return group.id;
  });
  return user.groups.filter(function (group) {
    return inventoryGroupIds.includes(group.id);
  }).some(function (group) {
    return group.isDelegate;
  }) || module.exports.hasRelationship(user, EDGE.DELEGATE, {
    groups: inventoryGroupIds
  });
};

// chemical
module.exports.hasWriteAccessToFamily = function (family, user) {
  return family.group && (user.groups.map(function (group) {
    return group.id;
  }).includes(family.group.id) || module.exports.hasRelationship(user, null, {
    groups: [family.group.id]
  })) || module.exports.isChemInfo(user);
};
module.exports.hasReadAccessToInventory = function (inventory, user) {
  return module.exports.hasChemAdminRead(inventory.campusCode, user) || module.exports.isMemberOrColleagueOfInventory(inventory, user) || module.exports.hasRoleWithReadAccessToInventory(inventory, user);
};
module.exports.hasReadAccessToContainer = function (container, user) {
  return module.exports.hasChemAdminRead(container.inventory.campusCode, user) || module.exports.hasWriteAccessToContainer(container, user) || !container.isPrivate && user.inventories.reduce(function (acc, inventory) {
    return acc.concat(inventory.colleagues.reduce(function (inventoryAcc, colleague) {
      return inventoryAcc.concat(colleague._id ? colleague._id.toString() : colleague.id.toString());
    }, []));
  }, []).includes(container.inventory._id.toString()) || module.exports.hasRelationship(user, null, {
    inventoryId: container.inventory._id.toString()
  });
};
module.exports.hasWriteAccessToContainer = function (container, user) {
  return (user.inventories || [{}]).some(function (inventory) {
    return inventory._id && inventory._id.toString() === container.inventory._id.toString();
  }) || module.exports.isChemAdmin(container.inventory.campusCode, user) || module.exports.hasRelationship(user, null, {
    inventoryId: container.inventory._id.toString()
  });
};
module.exports.hasReadAccessToLibrary = function (user) {
  return module.exports.isChemAdmin(user.campusCode, user) || module.exports.hasChemAdminRead(user.campusCode, user) || module.exports.isChemInfo(user) || module.exports.isControlAreaAdmin(user, user.campusCode);
};
module.exports.hasWriteAccessToLibrary = function (user) {
  return module.exports.isChemInfo(user);
};
module.exports.hasReadAccessToControlArea = function (user, controlArea) {
  return module.exports.isChemAdmin(user.campusCode, user) || module.exports.isSystemControlAreaAdmin(user, controlArea.tenantCode) || module.exports.isControlAreaAdmin(user, controlArea.campusCode);
};
module.exports.hasWriteAccessToControlArea = function (user, controlArea) {
  return module.exports.isSystemControlAreaAdmin(user, controlArea.tenantCode) || module.exports.isControlAreaAdmin(user, user.campusCode);
};
module.exports.hasWriteAccessToFacility = function (user, facility) {
  return user.campusCode === facility.campusCode && module.exports.isChemAdmin(facility.campusCode, user);
};
module.exports.hasLabHazardAdminRole = function (user) {
  return user.relationships.length > 0 && user.relationships.some(function (relation) {
    return relation.role === EDGE.LAB_HAZARD_ADMIN;
  });
};

//  # TODO: modify after mongo => neptune migration
module.exports.hasInternalToolsAccess = function (user, isNeptune) {
  return AnalyticsHelper.isAnalyticsAdmin(user, isNeptune);
};