#-*- coding: utf-8; -*-

module Mastermind

  class Code

    #0=Black, 1=Cyan, 2=Green, 3=Red, 4=Yellow, 5=White
    @@colours = [:black, :cyan, :green, :red, :yellow, :white]
    @@colour_map = {
      'b'=>:black,
      'c'=>:cyan,
      'g'=>:green,
      'r'=>:red,
      'y'=>:yellow,
      'w'=>:white
    }

    attr_reader :pegs

    def initialize(*some_pegs)
      @pegs = some_pegs
    end

    def Code.from_string(code_string)
      null_code = Code.new(:none, :none, :none, :none)
      return null_code if code_string.nil? 
      return null_code unless code_string.instance_of?(String) 
      return null_code if code_string.empty? 

      pegs = code_string.split(//).collect {|each| @@colour_map[each]}
      Code.new(*pegs)
    end

    def peg_at(number)
      @pegs[number]
    end

    def positions_of(colour)
      @pegs.collect {|each| each == colour}
    end

    def mark(guess)
      exact_match_mask = compute_exact_matches(guess)
      black = tally_black(exact_match_mask)
      white = tally_white(exact_match_mask, guess)

      Score.new(black, white)
    end

    def compute_exact_matches(guess)
      (0..3).collect {|each| self.peg_at(each) == guess.peg_at(each)}
    end

    def tally_black(exact_match_mask)
      (exact_match_mask.select {|each| each}).size
    end

    def tally_white(exact_match_mask, guess)
      (0..3).inject(0) do |sum, each|
        found_at = self.positions_of(guess.peg_at(each))
        found_at[each] = false
        (0..3).each {|i| found_at[i] = false if exact_match_mask[i]}
        if found_at.any? then sum + 1
        else sum
        end
      end
    end

  end

  #0=Black, 1=Cyan, 2=Green, 3=Red, 4=Yellow, 5=White
  @@colours = [:black, :cyan, :green, :red, :yellow, :white]

  def Code.generate_using(random_generator)
    pegs = []
    4.times {pegs << @@colours[random_generator.next]}
    Code.new(*pegs)
  end

end
