contract Policy is Ownable, EmergencySafe, Upgradeable{

  struct InsuranceProduct {
    uint inceptionDate;
    uint expirationDate;
    uint limitOfLiability;
    string limitOfLiabilityCurrency;
    string insuranceType;
    bytes32 policyDocumentReference;
  }

  struct PolicyInfo {
    uint blockNumber;
    uint numInsuranceProducts;
    string clientInfo;
    string ixlEnquiryId;
    string status;
    address brokerEtherAddress;
    address clientEtherAddress;
  }

  InsuranceProduct[] public insuranceProducts;
  PolicyInfo public policyInfo;
  mapping(address => bool) private cancellations;

  /**
   * @dev Throws if called by other account than broker or client
   */
  modifier participantOnly() {
    require(msg.sender == policyInfo.clientEtherAddress || msg.sender == policyInfo.brokerEtherAddress);
    _;
  }

  /**
   * @dev Throws if called by other account than broker or client,
   * core parameters kept as fields for future logic and for quick reference upon lookup
   */
  function Policy(string _clientInfo, address _brokerEtherAddress, address _clientEtherAddress, string _enquiryId) public {

    policyInfo = PolicyInfo({
      blockNumber: block.number,
      numInsuranceProducts: 0,
      clientInfo: _clientInfo,
      ixlEnquiryId: _enquiryId,
      status: 'In Force',
      clientEtherAddress: _clientEtherAddress,
      brokerEtherAddress: _brokerEtherAddress
    });

    allowedToUpgrade = false;
  }

  function addInsuranceProduct (uint _inceptionDate, uint _expirationDate, uint _limitOfLiability, string _limitOfLiabilityCurrency, string _insuranceType, bytes32 _policyDocReference) public ownerOnly isNotPaused {

    insuranceProducts.push(InsuranceProduct({
      policyDocumentReference: _policyDocReference,
      inceptionDate: _inceptionDate,
      expirationDate: _expirationDate,
      limitOfLiability: _limitOfLiability,
      limitOfLiabilityCurrency: _limitOfLiabilityCurrency,
      insuranceType: _insuranceType
    }));

    policyInfo.numInsuranceProducts++;
  }


  /**
   * @dev Allows broker and client to cancel contract, when both have cancelled,
   * status is updated and contract becomes upgradeable
   */
  function revokeContract() public participantOnly {
    cancellations[msg.sender] = true;

    if (((cancellations[policyInfo.brokerEtherAddress] && (cancellations[policyInfo.clientEtherAddress] || cancellations[owner]))
        || (cancellations[policyInfo.clientEtherAddress] && cancellations[owner]))){
      policyInfo.status = "REVOKED";
      allowedToUpgrade = true;
    }
  }
}
/**
 * @title Insurance Contract
 * @dev Insurance Contract that is created by broker/client, functions mainly as permament record store
 */
function Policy(string _clientInfo, address _brokerEtherAddress, address _clientEtherAddress, string _enquiryId) public {

  policyInfo = PolicyInfo({
    blockNumber: block.number,
    numInsuranceProducts: 0,
    clientInfo: _clientInfo,
    ixlEnquiryId: _enquiryId,
    status: 'In Force',
    clientEtherAddress: _clientEtherAddress,
    brokerEtherAddress: _brokerEtherAddress
  });

  allowedToUpgrade = false;
}

/**
 * @dev Throws if called by other account than broker or client,
 * core parameters kept as fields for future logic and for quick reference upon lookup
 */