<!DOCTYPE html>
<html>

  <head>
    <link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
    <link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" />
    <script data-require="bootstrap@*" data-semver="3.3.5" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script data-require="bootstrap@*" data-semver="3.3.5" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script>
    <script data-require="jquery@*" data-semver="2.1.4" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <div id="container" class="container"></div>
    <script src="https://fb.me/react-0.13.3.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
    <script type="text/jsx" src="script.jsx"></script>
  </body>

</html>
var AnswerFrame = React.createClass({
  render: function(){
    var props = this.props;
    var selectedNumbers = props.selectedNumbers.map(function(i){
      return (
          <span onClick={props.unselectNumber.bind(null, i)}>{i}</span>
        );
    });
    return (
        <div id="answer-frame">
          <div className="well">
            {selectedNumbers}
          </div>
        </div>
      )
  }
});

var NumbersFrame = React.createClass({
  render: function(){
    var numbers = [], className, 
        selectNumber = this.props.selectNumber,
        selectedNumbers = this.props.selectedNumbers,
        usedNumbers = this.props.usedNumbers;
    for(var i = 1; i <= 9; i++){
      className = "number selected-"+ (selectedNumbers.indexOf(i)>=0);
      className += " used-"+ (usedNumbers.indexOf(i)>=0);
      numbers.push(<div className={className} onClick={selectNumber.bind(null, i)}>{i}</div>)
    }
    return (
        <div id="numbers-frame">
          <div className="well">
            {numbers}
          </div>
        </div>
      )
  }
});

var ButtonFrame = React.createClass({
  render: function(){
    var disabled, button, correct = this.props.correct;
    
    switch(correct){
      case true:
        button = (<button className="btn btn-success btn-lg" onClick={this.props.acceptAnswer}><span className="glyphicon glyphicon-ok"></span></button>)
        break;
      case false:
        button = (<button className="btn btn-danger btn-lg"><span className="glyphicon glyphicon-remove"></span></button>)
        break;
      default: 
        disabled = this.props.selectedNumbers.length === 0;
        button = (<button className="btn btn-primary btn-lg" disabled={disabled} onClick={this.props.checkAnswer}>=</button>)
    }

    return (
        <div id="button-frame">
          {button}
          <br /><br/>
          <button className="btn btn-warning btn-xs" onClick={this.props.redraw} disabled={this.props.redraws === 0}>
            <span className="glyphicon glyphicon-refresh"></span>
            &nbsp;
            {this.props.redraws}
          </button>
        </div>
      )
  }
});

var StarsFrame = React.createClass({
  render: function(){
    var stars = [];
    for(var i = 0; i < this.props.numberOfStars; i++){
      stars.push(<span className="glyphicon glyphicon-star"></span>)
    }
    return (
        <div id="stars-frame">
          <div className="well">
            {stars}
          </div>
        </div>
      )
  }
});

var DoneFrame = React.createClass({
  render: function(){
    return (
      <div className="well text-center">
        <h2>{this.props.doneStatus}</h2>
        <button className="btn btn-default" onClick={this.props.resetGame}>Play Again</button>
      </div>);
  }
});

var Game = React.createClass({
  getInitialState: function(){
    return {
      numberOfStars: this.randomNumber(), 
      selectedNumbers: [],
      correct: null,
      usedNumbers: [],
      redraws: 5,
      doneStatus: null
    };
  },
  resetGame: function(){
    this.replaceState(this.getInitialState());
  },
  randomNumber: function(){
    return Math.floor(Math.random()*9) + 1;
  },
  selectNumber: function(clickedNumber){
    if(this.state.selectedNumbers.indexOf(clickedNumber) < 0){
    this.setState(
      {selectedNumbers: this.state.selectedNumbers.concat(clickedNumber),
        correct: null
      }
      );
    }
  },
  unselectNumber: function(clickedNumber){
    var selectedNumbers = this.state.selectedNumbers,
        indexOfNumber = selectedNumbers.indexOf(clickedNumber);
        
      selectedNumbers.splice(indexOfNumber, 1);
      this.setState({selectedNumbers: selectedNumbers, correct: null});
  },
  checkAnswer: function(){
    var correct = (this.state.numberOfStars === this.sumOfSelectedNumbers());
    this.setState({correct: correct});
  },
  sumOfSelectedNumbers: function(){
    return this.state.selectedNumbers.reduce(function(p,n){
      return p+n;
    },0);
  },
  acceptAnswer: function(){
    var usedNumbers = this.state.usedNumbers.concat(this.state.selectedNumbers);
    this.setState({
      selectedNumbers: [],
      usedNumbers: usedNumbers,
      correct: null,
      numberOfStars: this.randomNumber()
    }, function(){
      this.updateDoneStatus();
    });
  },
  redraw: function(){
    if(this.state.redraws > 0){
      this.setState({
        numberOfStars: this.randomNumber(), 
        correct: null,
        selectedNumbers: [],
        redraws: this.state.redraws -1
      }, function(){
        this.updateDoneStatus();
      });
    }
  },
  possibleSolutions: function(){
    var numberOfStars = this.state.numberOfStars,
        possibleNumbers = [],
        usedNumbers = this.state.usedNumbers;
        
    for(var i=1; i <=9; i++){
      if(usedNumbers.indexOf(i) < 0){
        possibleNumbers.push(i);
      }
    }
    
    return possibleCombinationSum(possibleNumbers, numberOfStars);
  },
  updateDoneStatus: function(){
    if(this.state.usedNumbers.length === 9){
      this.setState({doneStatus: 'Done. Nice!'})
      return;
    }
    if(this.state.redraws === 0 && !this.possibleSolutions()){
      this.setState({doneStatus: 'Game Over!'});
    }
  },
  render: function(){
    var selectedNumbers = this.state.selectedNumbers,
        numberOfStars = this.state.numberOfStars,
        correct = this.state.correct,
        usedNumbers = this.state.usedNumbers,
        doneStatus = this.state.doneStatus,
        redraws = this.state.redraws,
        bottomFrame;
        
    if(doneStatus){
      bottomFrame = <DoneFrame doneStatus={doneStatus} resetGame={this.resetGame} />;
    }else{
      bottomFrame = <NumbersFrame selectedNumbers={selectedNumbers} 
                                  selectNumber={this.selectNumber} 
                                  usedNumbers={usedNumbers} />;
    }
    return (
        <div id="game">
          <h2>Play Nine</h2>
          <p>Use the number circles below to match how many stars are shown. If you get stuck, click the redraw button. You only get 5 redraws.</p>
          <hr/>
          <div className="clearfix">
            <StarsFrame   numberOfStars={numberOfStars}/>
            
            <ButtonFrame  selectedNumbers={selectedNumbers} 
                          correct={correct} 
                          checkAnswer={this.checkAnswer} 
                          acceptAnswer={this.acceptAnswer} 
                          redraw={this.redraw}
                          redraws={redraws} />
            
            <AnswerFrame  selectedNumbers={selectedNumbers} 
                          unselectNumber={this.unselectNumber} />
          </div>
          
          {bottomFrame}
        </div>
      )
  }
});

React.render(
  <Game />,
  document.getElementById('container')
);



// Function below was copied from https://gist.github.com/samerbuna/aa1f011a6e42d6deba46
// Skip it and move on to the React Stuff
var possibleCombinationSum = function(arr, n) {
  if (arr.indexOf(n) >= 0) { return true; }
  if (arr[0] > n) { return false; }
  if (arr[arr.length - 1] > n) {
    arr.pop();
    return possibleCombinationSum(arr, n);
  }
  var listSize = arr.length, combinationsCount = (1 << listSize)
  for (var i = 1; i < combinationsCount ; i++ ) {
    var combinationSum = 0;
    for (var j=0 ; j < listSize ; j++) {
      if (i & (1 << j)) { combinationSum += arr[j]; }
    }
    if (n === combinationSum) { return true; }
  }
  return false;
};
#stars-frame .glyphicon {
  margin: 0.3em;
  font-size: 1.75em;
}

#stars-frame, #answer-frame {
  width: 40%;
  float: left;
}

#button-frame {
  width: 20%;
  float: left;
  text-align: center;
  margin-top: 75px;
}

#stars-frame .well, #answer-frame .well {
  height: 200px;
}

#numbers-frame .number, #answer-frame .well span {
  display: inline-block;
  margin: 0.5em;
  background-color: #bbb;
  width: 30px;
  text-align: center;
  font-size: 22px;
  border-radius: 50%;
  cursor: pointer;
}

#numbers-frame .selected-true {
  background-color: #e8e8e8;
  color: #ddd;
  cursor: not-allowed;
}

#numbers-frame .used-true {
  background-color: #aaddaa;
  color: #99bb99;
  cursor: not-allowed;
}