pragma solidity ^0.4.11;

/** @title Decentralized Identification Number (DIN) registry. */
contract DINRegistry {

    struct Record {
        address owner;
        address resolver;  // Address where product information is stored. 
        uint256 updated;   // Unix timestamp.
    }

    // DIN => Record
    mapping (uint256 => Record) records;

    // The address of DINRegistrar.
    address public registrar;

    // The first DIN registered.
    uint256 public genesis;

    modifier only_registrar {
        require(registrar == msg.sender);
        _;
    }

    modifier only_owner(uint256 DIN) {
        require(records[DIN].owner == msg.sender);
        _;
    }

    // Logged when the owner of a DIN transfers ownership to a new account.
    event NewOwner(uint256 indexed DIN, address indexed owner);

    // Logged when the resolver associated with a DIN changes.
    event NewResolver(uint256 indexed DIN, address indexed resolver);

    // Logged when a new DIN is registered.
    event NewRegistration(uint256 indexed DIN, address indexed owner);

    // Logged when the DINRegistrar contract changes.
    event NewRegistrar(address indexed registrar);

    /** @dev Constructor.
      * @param _genesis The first DIN registered.
      */
    function DINRegistry(uint256 _genesis) {
        genesis = _genesis;

        // Register the genesis DIN to the account that deploys this contract.
        records[genesis].owner = msg.sender;
        records[genesis].updated = block.timestamp;
        NewRegistration(genesis, msg.sender);
    }

    // Get the owner of a specified DIN.
    function owner(uint256 DIN) constant returns (address) {
        return records[DIN].owner;
    }

    /**
     * @dev Transfer ownership of a DIN.
     * @param DIN The DIN to transfer.
     * @param owner The address of the new owner.
     */
    function setOwner(uint256 DIN, address owner) only_owner(DIN) {
        records[DIN].owner = owner;
        records[DIN].updated = block.timestamp;
        NewOwner(DIN, owner);
    }

    // Get the resolver of a specified DIN.
    function resolver(uint256 DIN) constant returns (address) {
        return records[DIN].resolver;
    }

    /**
     * @dev Set the resolver of a DIN.
     * @param DIN The DIN to update.
     * @param resolver The address of the resolver.
     */
    function setResolver(uint256 DIN, address resolver) only_owner(DIN) {
        records[DIN].resolver = resolver;
        records[DIN].updated = block.timestamp;
        NewResolver(DIN, resolver);
    }

    // Get the time a specified DIN record was last updated.
    function updated(uint256 DIN) constant returns (uint256) {
        return records[DIN].updated;
    } 

    /**
     * @dev Register a new DIN.
     * @param owner The account that will own the DIN.
     */
    function register(uint256 DIN, address owner) only_registrar {
        records[DIN].owner = owner;
        records[DIN].updated = block.timestamp;
        NewRegistration(DIN, owner);
    }

    /**
     * @dev Change the DINRegistrar contract.
     * @param _registrar The address of the new registrar.
     */
    function setRegistrar(address _registrar) only_owner(genesis) {
        registrar = _registrar;
        NewRegistrar(_registrar);
    }

}

/** @title Decentralized Identification Number (DIN) registrar. Registers new DINs */
contract DINRegistrar {

    // The DINRegistry contract
    DINRegistry registry;

    // The current DIN index. DINs are registered sequentially.
    uint256 public index;

    // The maximum amount of DINs that can be registered in a single transaction.
    uint256 public MAX_QUANTITY = 10;

    /** @dev Constructor.
      * @param _registry The DINRegistry contract.
      */
    function DINRegistrar(DINRegistry _registry, uint256 _genesis) {
        registry = _registry;

        // Set the current index to the genesis DIN.
        index = _genesis;
    }

    /**
     * @dev Register a new DIN.
     * @return DIN The newly registered DIN.
     */
    function registerDIN() returns (uint256 DIN) {
        index++;
        registry.register(index, msg.sender);
        return index;
    }

    /**
     * @dev Register multiple new DINs.
     * @param quantity The amount of DINs to register.
     */
    function registerDINs(uint256 quantity) {
        require(quantity <= MAX_QUANTITY);

        for (uint i = 0; i < quantity; i++) {
            registerDIN();
        }
    }

}