$:.push "."
$:.push "/usr/local/rvm/gems/ruby-2.1.2/gems/mysql2-0.3.16/lib"
require 'sinatra'
require 'lib/sql_wrapper'
require 'controllers/user'
require 'controllers/puzzle'
require 'json'
require 'config'

set :allow_methods, [:get, :post]
set :allow_credentials, true
set :max_age, "1728000"
set :expose_headers, ['Content-Type']
set :port, AltHack::Config[:port]
set :bind, AltHack::Config[:ip]

if AltHack::Config[:socket]
  SQLWrapper.socket = AltHack::Config[:socket]
end

set(:auth) do |req|
  condition do
    if req == :user
      @user = User.new(params[:unique])
      return @user.valid?
    elsif req == :owner
      begin
        @user = User.new(params[:unique])
        @puzzle = Puzzle.new(params[:puzzle])

        return @puzzle.get('creator') == @user.id
      rescue
        p $!, $!.backtrace
        return false
      end
    elsif req == :puzzle
      begin
        @puzzle = Puzzle.new(params[:puzzle])
      rescue
        return false
      end
    elsif req == :secret
      if params[:secret] != AltHack::Config[:secret]
        return false
      end
    end
  end
end

post '/user/login' do
  # Does this user already exist?
  begin
    user = User.new(params[:unique])
    if user.valid?
      return [202, "#{user.id}"]
    end
  rescue
    # Nae worries, we'll just try to create
  end

  # Register new user
  begin
    user = User.create(params[:unique], params[:alias])
    if user.valid?
      return [201, "#{user.id}"]
    end
  rescue
    return [400, "nope"]
  end

  return [400, "confused"]
end

get '/user/puzzles', :auth => :user do
  puzzles = @user.puzzles.map { |x| x.to_map }

  content_type 'application/json'
  return puzzles.to_json
end

post '/puzzle/create', :auth => :user do
  puzzle = Puzzle.create(@user, params[:json])

  if puzzle.nil?
    return [400, "nope"]
  else
    return [201, "#{puzzle.id}"]
  end
end

get '/puzzle/random' do
  begin
    puzzle = Puzzle.random

    content_type 'application/json'
    return puzzle.to_json
  rescue
    return [400, "nope"]
  end
end

get '/puzzle/curated' do
  begin
    puzzle = Puzzle.curated

    content_type 'application/json'
    return puzzle.to_json
  rescue
    return [400, "nope"]
  end
end

post '/puzzle/activate', :auth => :owner do
  @puzzle.update({'active' => (params[:state] == "true" ? 1 : 0)})
end

post '/puzzle/flag', :auth => :puzzle do
  @puzzle.update({'flag' => 1})
end

post '/puzzle/curate', :auth => :secret do
  @puzzle = Puzzle.new(params[:puzzle])
  @puzzle.update({'curate' => 1})
end

post '/puzzle/rate', :auth => :puzzle do
  @puzzle.rate(params[:rating] == "positive")
end

post '/puzzle/attempt', :auth => :puzzle do
  @puzzle.attempt(params[:count].to_i)
end
