contract BillsOfExchangeFactory is ManagedContractWithPaidService {

    // using SafeMath for uint256;

    /*
    * Legal conditions to be included
    */
    string public description = "Every token (ERC20) in this smart contract is a bill of exchange in blank - payable to bearer (bearer is the owner of the Ethereum address witch holds the tokens, or the person he/she represents), but not to order - that means no endorsement possible and the token holder can only transfer the token (bill of exchange in blank) itself.";
    // string public forkClause = "";
    string public order = "Pay to bearer (tokenholder), but not to order, the sum defined for every token in currency defined in 'currency' (according to ISO 4217 standard; or XAU for for one troy ounce of gold, XBT or BTC for Bitcoin, ETH for Ether, DASH for Dash, ZEC for Zcash, XRP for Ripple, XMR for Monero, xEUR for xEuro)";
    string public disputeResolutionAgreement =
    "Any dispute, controversy or claim arising out of or relating to this bill(s) of exchange, including invalidity thereof and payments based on this bill(s), shall be settled by arbitration in accordance with the Cryptonomica Arbitration Rules (https://github.com/Cryptonomica/arbitration-rules) in the version in effect at the time of the filing of the claim. In the case of the Ethereum blockchain fork, the blockchain that has the highest hashrate is considered valid, and all others are not considered a valid registry; bill payment settles bill even if valid blockchain (hashrate) changes after the payment. All Ethereum test networks are not valid registries.";

    /**
    *  Constructor
    */
    constructor() public {

        isAdmin[msg.sender] = true;

        changePrice(0.15 ether);

        // Ropsten: > verification always valid for any address
        // TODO: change in production to https://etherscan.io/address/0x846942953c3b2A898F10DF1e32763A823bf6b27f <<<<<<<<
        // require(changeCryptonomicaVerificationContractAddress(0xE48BC3dB5b512d4A3e3Cd388bE541Be7202285B5)); // Ropsten
        require(changeCryptonomicaVerificationContractAddress(0x846942953c3b2A898F10DF1e32763A823bf6b27f));

        require(setWithdrawalAddress(msg.sender));
    }

    /**
    * every bills of exchange contract will have a number
    */
    uint256 public billsOfExchangeContractsCounter;

    /**
    * ledger bills of exchange contract number => bills of exchange contract address
    */
    mapping(uint256 => address) public billsOfExchangeContractsLedger;

    /*
    * @param _name Name of the token, also will be used for erc20 'symbol' property (see billsOfExchange.initToken )
    * @param _totalSupply Number (amount) of bills of exchange to create
    * @param __currency A currency in which bill payments have to be made, for example: "EUR", "USD"
    * @param _sumToBePaidForEveryToken A sum of each bill of exchange
    * @param _drawerName The name of the person (legal or physical) who issues the bill (drawer)
    * @param _drawee The name of the person (legal or physical) who is to pay (drawee)
    * @param __draweeSignerAddress Ethereum address of the person who has to accept bills of exchange in the name of
    * the drawee. Drawer has to agree this address with the drawee (acceptor) in advance.
    * @param _timeOfPayment Time when bill payment has to be made
    * @param _placeWhereTheBillIsIssued A statement of the place where the bill is issued.
    * Usual it's the address of the drawer.
    * @param _placeWherePaymentIsToBeMadeA statement of the place where payment is to be made.
    * Usual it's the address of the drawee.
    *
    * arguments to test this function in remix:
    * "Test Company Ltd. bills of exchange, Series TST01", "TST01", 100000000, "EUR",1,"Test Company Ltd, 3 Main Street, London, XY1Z  1XZ, U.K.; company # 12345678","https://beta.companieshouse.gov.uk/company/12345678/officers","Test Company Ltd, 3 Main Street, London, XY1Z  1XZ, U.K.; company # 12345678",0x07BaD6bda22A830f58fDA19eBA45552C44168600,"at sight but not before 01 Sep 2021","London, U.K.", "London, U.K."
    */
    function createBillsOfExchange(
        string memory _name,
        string memory _symbol,
        uint256 _totalSupply,
        string memory _currency,
        uint256 _sumToBePaidForEveryToken,
        string memory _drawerName,
    // address _drawerRepresentedBy, // <<< msg.sender
        string memory _linkToSignersAuthorityToRepresentTheDrawer,
        string memory _drawee,
        address _draweeSignerAddress,
        string memory _timeOfPayment,
        string memory _placeWhereTheBillIsIssued,
        string memory _placeWherePaymentIsToBeMade
    ) public payable returns (address newBillsOfExchangeContractAddress) {

        require(msg.value >= price, "Payment sent was lower than the price for creating Bills of Exchange");

        BillsOfExchange billsOfExchange = new BillsOfExchange();
        billsOfExchangeContractsCounter++;
        billsOfExchangeContractsLedger[billsOfExchangeContractsCounter] = address(billsOfExchange);

        billsOfExchange.initToken(
            _name, //
            _symbol, // symbol
            _totalSupply,
            msg.sender // tokenOwner (drawer or drawer representative)
        );

        billsOfExchange.initBillsOfExchange(
            billsOfExchangeContractsCounter,
            _currency,
            _sumToBePaidForEveryToken,
            _drawerName,
            msg.sender,
            _linkToSignersAuthorityToRepresentTheDrawer,
            _drawee,
            _draweeSignerAddress
        );

        billsOfExchange.setPlacesAndTime(
            _timeOfPayment,
            _placeWhereTheBillIsIssued,
            _placeWherePaymentIsToBeMade
        );

        billsOfExchange.setLegal(
            description,
            order,
            disputeResolutionAgreement,
            address(cryptonomicaVerification)
        );

        /*
        * (!) Here we check if msg.sender has valid verification from 'cryptonomicaVerification' contract
        */
        billsOfExchange.signDisputeResolutionAgreementFor(msg.sender, _drawerName);

        return address(billsOfExchange);
    }

    /*
    * As above, but the drawer and the drawee are the same person, and bills will be accepted instantly
    *
    * arguments to test this function in remix:
    * "Test Company Ltd. bills of exchange, Series TST01", "TST01", 100000000, "EUR",1,"Test Company Ltd, 3 Main Street, London, XY1Z  1XZ, U.K.; company # 12345678","https://beta.companieshouse.gov.uk/company/12345678/officers","at sight but not before 01 Sep 2021","London, U.K.", "London, U.K."
    */
    function createAndAcceptBillsOfExchange(
        string memory _name, // name of the token
        string memory _symbol,
        uint256 _totalSupply,
        string memory _currency,
        uint256 _sumToBePaidForEveryToken,
        string memory _drawerName,
    // address _drawerRepresentedBy, // <<< msg.sender
        string memory _linkToSignersAuthorityToRepresentTheDrawer,
    // string  _drawee, > the same as drawer
    // address _draweeSignerAddress, > the same as msg.sender
        string memory _timeOfPayment,
        string memory _placeWhereTheBillIsIssued,
        string memory _placeWherePaymentIsToBeMade

    ) public payable returns (address newBillsOfExchangeContractAddress) {// if 'external' > "Stack to deep ..." error

        require(msg.value >= price, "Payment sent was lower than the price for creating Bills of Exchange");

        BillsOfExchange billsOfExchange = new BillsOfExchange();
        billsOfExchangeContractsCounter++;
        billsOfExchangeContractsLedger[billsOfExchangeContractsCounter] = address(billsOfExchange);

        billsOfExchange.initToken(
            _name, //
            _symbol, // symbol
            _totalSupply,
            msg.sender // tokenOwner (drawer or drawer representative)
        );

        billsOfExchange.initBillsOfExchange(
            billsOfExchangeContractsCounter,
            _currency,
            _sumToBePaidForEveryToken,
            _drawerName,
            msg.sender,
            _linkToSignersAuthorityToRepresentTheDrawer,
            _drawerName, // < _drawee,
            msg.sender // < _draweeSignerAddress
        );

        billsOfExchange.setPlacesAndTime(
            _timeOfPayment,
            _placeWhereTheBillIsIssued,
            _placeWherePaymentIsToBeMade
        );

        billsOfExchange.setLegal(
            description,
            order,
            disputeResolutionAgreement,
            address(cryptonomicaVerification)
        );

        // not needed to sign dispute resolution agreement here because signature is required by 'accept' function

        billsOfExchange.accept(_linkToSignersAuthorityToRepresentTheDrawer);

        return address(billsOfExchange);

    }

}
//contract BillsOfExchangeFactory is ManagedContractWithPaidService, ManagedContractUsingCryptonomicaServices {
function createBillsOfExchange(
    string memory _name,
    string memory _symbol,
    uint256 _totalSupply,
    string memory _currency,
    uint256 _sumToBePaidForEveryToken,
    string memory _drawerName,
// address _drawerRepresentedBy, // <<< msg.sender
    string memory _linkToSignersAuthorityToRepresentTheDrawer,
    string memory _drawee,
    address _draweeSignerAddress,
    string memory _timeOfPayment,
    string memory _placeWhereTheBillIsIssued,
    string memory _placeWherePaymentIsToBeMade
) public payable returns (address newBillsOfExchangeContractAddress) {

    require(msg.value >= price, "Payment sent was lower than the price for creating Bills of Exchange");

    BillsOfExchange billsOfExchange = new BillsOfExchange();
    billsOfExchangeContractsCounter++;
    billsOfExchangeContractsLedger[billsOfExchangeContractsCounter] = address(billsOfExchange);

    billsOfExchange.initToken(
        _name, //
        _symbol, // symbol
        _totalSupply,
        msg.sender // tokenOwner (drawer or drawer representative)
    );

    billsOfExchange.initBillsOfExchange(
        billsOfExchangeContractsCounter,
        _currency,
        _sumToBePaidForEveryToken,
        _drawerName,
        msg.sender,
        _linkToSignersAuthorityToRepresentTheDrawer,
        _drawee,
        _draweeSignerAddress
    );

    billsOfExchange.setPlacesAndTime(
        _timeOfPayment,
        _placeWhereTheBillIsIssued,
        _placeWherePaymentIsToBeMade
    );

    billsOfExchange.setLegal(
        description,
        order,
        disputeResolutionAgreement,
        address(cryptonomicaVerification)
    );

    /*
    * (!) Here we check if msg.sender has valid verification from 'cryptonomicaVerification' contract
    */
    billsOfExchange.signDisputeResolutionAgreementFor(msg.sender, _drawerName);

    return address(billsOfExchange);
}

/*
 * @param _name Name of the token, also will be used for erc20 'symbol' property (see billsOfExchange.initToken )
 * @param _totalSupply Number (amount) of bills of exchange to create
 * @param __currency A currency in which bill payments have to be made, for example: "EUR", "USD"
 * @param _sumToBePaidForEveryToken A sum of each bill of exchange
 * @param _drawerName The name of the person (legal or physical) who issues the bill (drawer)
 * @param _drawee The name of the person (legal or physical) who is to pay (drawee)
 * @param __draweeSignerAddress Ethereum address of the person who has to accept bills of exchange in the name of
 * the drawee. Drawer has to agree this address with the drawee (acceptor) in advance.
 * @param _timeOfPayment Time when bill payment has to be made
 * @param _placeWhereTheBillIsIssued A statement of the place where the bill is issued.
 * Usual it's the address of the drawer.
 * @param _placeWherePaymentIsToBeMadeA statement of the place where payment is to be made.
 * Usual it's the address of the drawee.
 *
 * arguments to test this function in remix:
 * "Test Company Ltd. bills of exchange, Series TST01", "TST01", 100000000, "EUR",1,"Test Company Ltd, 3 Main Street, London, XY1Z  1XZ, U.K.; company # 12345678","https://beta.companieshouse.gov.uk/company/12345678/officers","Test Company Ltd, 3 Main Street, London, XY1Z  1XZ, U.K.; company # 12345678",0x07BaD6bda22A830f58fDA19eBA45552C44168600,"at sight but not before 01 Sep 2021","London, U.K.", "London, U.K."
 */