function assert(exp, message) {
  if (!exp) {
    throw message;
  }
}

// My goodness javascript is lame
function compareArrays(a, b)
{
    if (typeof(a) != "object"){
        return a == b;
    }

    if (typeof(b) != "object"){
        return a == b;
    }

    if (a.length != b.length){
        return false;
    }

    for (var i=0; i < a.length; i += 1){
        if (!compareArrays(a[i], b[i])){
            return false;
        }
    }
    return true;
}


function find(lst, item){
    var found = -1;
    lst.map(function (x, index) {
        if (compareArrays(x, item)){
            found = index;
            // early exits are for people you like indices
        }
    });
    return found;
}

function parseSiteswap(siteswap){
    var sum = 0;
    var throws = [];
    for (var i=0; i < siteswap.length; i++){
        var beats = parseInt(siteswap[i])
        throws.push(beats);
        sum += beats;
    }
    
    assert(sum % siteswap.length == 0, "*really* not a valid siteswap");
    return throws;
}

function extendWithZeros(lst, length){
    var newList = lst.slice()
    for (var i=0; i < length - lst.length; i += 1){
        newList.push(0);
    }
    return newList;
}

function cycle(lst, times){
    var output = [];
    for (var k=0; k < times; k++){
        output = output.concat(lst);
    }
    return output;
}

function reduce(lst, func){
    a = lst[0]
    for (var i=1; i < lst.length; i += 1){
        a = func(a, lst[i])
    }
    return a;
}

function rotateList(lst, forward){
    return lst.slice(forward).concat(lst.slice(0,forward));
}
 
function iterateState(state, beats){
        // Find the next state after a throw with a given number of beats
        state = state.slice();

        state[0] -= 1; // throw
        state[0] = Math.max(state[0], 0);

        var falling = state.slice(2).concat([0]);
        state[0] += falling[0];

        falling = falling.slice(1)

        var newState = [state[1], state[0]].concat(falling);

        newState = extendWithZeros(newState, beats);
        newState[beats - 1] += 1;
        return newState;
}

function getStates(throws){
    var balls = reduce(throws, function (x, y) { return x + y; }) / throws.length; 

    var highestThrow = reduce(throws, Math.max);
    var stableAfter = Math.ceil(highestThrow / throws.length) * throws.length;
    
    var state = [0, 0];
    for (var i=0; i < stableAfter; i++)
        state = iterateState(state, throws[i % throws.length]);

    var states = [];
    for (var i=0; i < throws.length; i++){
        states.push(state) 
        state = iterateState(state, throws[i % throws.length])
    }
    return states;

}

