pragma solidity ^0.4.4;
contract CrowdFunding {
    // data structure to hold information about campaign contributors
    struct Funder {
        address addr;
        uint amount;
    }
    // Campaign data structure
    struct Campaign {
        address beneficiary;
        uint fundingGoal;
        uint numFunders;
        uint amount;
        uint deadline;
        mapping (uint => Funder) funders;
        mapping (address => uint) balances;
    }
    //Declares a state variable 'numCampaigns'
    uint numCampaigns;
    //Creates a mapping of Campaign datatypes
    mapping (uint => Campaign) campaigns;
    //first function sets up a new campaign
    function newCampaign(address beneficiary, uint goal, uint deadline) returns (uint campaignID) {
        campaignID = numCampaigns++; // campaignID is return variable
        Campaign c = campaigns[campaignID]; // assigns reference
        c.beneficiary = beneficiary;
        c.fundingGoal = goal;
        c.deadline = block.number + deadline;
    }
    //function to contributes to the campaign
    function contribute(uint campaignID) {
        Campaign c = campaigns[campaignID];
        Funder f = c.funders[c.numFunders++];
        f.addr = msg.sender;
        f.amount = msg.value;
        c.amount += f.amount;
    }
    // checks if the goal or time limit has been reached and ends the campaign
    function checkGoalReached(uint campaignID) returns (bool reached) {
        Campaign c = campaigns[campaignID];
        if (c.amount >= c.fundingGoal){
            uint i = 0;
            uint f = c.numFunders;
            c.beneficiary.send(c.amount);
            c.amount = 0;
            c.beneficiary = 0;
            c.fundingGoal = 0;
            c.deadline = 0;
            c.numFunders = 0;
            while (i <= f){
                c.funders[i].addr = 0;
                c.funders[i].amount = 0;
                i++;
            }
        return true;
        }
        if (c.deadline <= block.number){
            uint j = 0;
            uint n = c.numFunders;
            c.beneficiary = 0;
            c.fundingGoal = 0;
            c.numFunders = 0;
            c.deadline = 0;
            c.amount = 0;
            while (j <= n){
                c.funders[j].addr.send(c.funders[j].amount);
                c.funders[j].addr = 0;
                c.funders[j].amount = 0;
                j++;
            }
            return true;
        }
        return false;
    }
}