#!/usr/bin/env shoes
require 'yaml'

# Require librairies
Dir['./static/lib/*'].collect{|f| File.basename(f, '.rb')}.each {|l| require "./static/lib/#{l}" }

# Unicode is coooooool :D
$KCODE = 'u'

Shoes.app :width => 600, :height => 500, :title => "Seditious" do

  # Application variables
  @err = YAML.load_file('./static/errors.yml').symbolize_keys
  @sed = SedFrontend.new
  @p_colors = {
    'UV' => '#a9a9a9',
    'I'  => '#4b0082',
    'Vi' => '#800080',
    'B'  => '#313bff',
    'V'  => '#006400',
    'J'  => '#c4b963',
    'Ba' => '#ff6dba',
    'O'  => '#eaaf67',
    'R'  => '#dc7777',
    'IR' => '#a9a9a9'
  }
  
  # Styles and background
  style(Shoes::Banner, :stroke => white, :font => "sans 24px")
  style(Shoes::Title, :stroke => white, :font => "sans italic 20px")    
  background '#eee'
  

  # App methods, prefixed with an underscore to avoid conflicts with Shoes and
  # to differenciate them.
  
  def _error(code, *format_args, &blk)
    alert(@err[code] % format_args)
    yield if block_given?
  end
  
  def _header(opts = {})
    opts = {:background => '#a9a9a9', :user => nil}.merge!(opts)
    @header.clear do
      background '#eee'
      background opts[:background], :radius => 8, :margin => 4
      if opts[:user].nil?
        banner "Seditious", :margin => 10
      else
        u = opts[:user]
        user = "%s-%s-%s" % [u.name, u.color, u.sector]
        banner "Seditious / ", 
          em(user, :stroke => '#eee', :font => 'italic 20px'), :margin => 10
      end
    end
  end
  
  def _page_header(page_title)
    background '#999', :radius => 8
    stack { title page_title, :margin => 5, :width => 1.0 }
  end
  
  def _todo_para(txt)
    para txt, ' ', link('fait', :font => '10px') {|x| 
      @seduser.todo_delete(txt)
      @seduser.todo_dump!
      x.parent.remove
    }, :margin => 5
  end
  
  def _index
    @contents.clear do 
      stack :margin => 10 do
        unless @sed.users.empty?
          para  "Entrez votre nom d'utilisateur ci-dessous et cliquez sur OK"
          flow :margin => 5 do
            user = edit_line 'Utilisateur', :width => 200
            button 'OK' do
              if user.text.nil?
                _error 100
              elsif !@sed.users.collect{|u| u.name }.include?(user.text)
                _error 101, user.text
              else
                _userpage(user.text)
              end
            end
          end
          para "Pas encore de compte ? ", 
            link("Cliquez ici pour en créer un !") { _register }
        else
          para "Première fois que vous lancez Seditious ?", 
            :font => "Sans Bold 20px", :margin => 5
          para link("Cliquez ici") { _register }, " pour créer un compte utilisateur."
        end
        stack :margin => 10 do
          para  "Seditious est un outil personel pour les utilisateurs du site ",
                link("Parano.be", :click => 'http://parano.be/'),
                ". Il permet de gérer ses propagandes (les éditer, préciser leur ",
                "date de publication, les classer...) et propose une petite todo-list ",
                "pour noter les choses que vous devez faire.",
                :font => "sans 10px", :stroke => '#555'
        end
      end
    end
  end
  
  def _register
    @contents.clear do
      stack :margin => 10 do
        background '#999', :radius => 8
        title "Nouveau compte"
        
        stack :margin => 10 do
          stack :margin => 10 do
            para "Login : (a-z A-Z 0-9 _ - uniquement)"
            flow(:margin => 10) { @login = edit_line }
          end
          stack :margin => 10 do
            para "Nom : "
            flow(:margin => 10) { @name = edit_line }
          end
          stack :margin => 10 do
            para "Couleur :"
            flow(:margin => 10) { @color = list_box :items => %w(UV I Vi B V J Ba O IR) }
          end
          stack :margin => 10 do
            para "Secteur :"
            flow(:margin => 10) { @sector = edit_line :width => 50 }
          end
          stack :margin => 10 do
            para "Éditeur de texte :"
            flow :margin => 10 do
              @editor = edit_line
              button("Choisir") { path = ask_open_file; @editor.text = path }
            end
          end
        end
        
        stack :margin => 10 do 
          button "Créer l'utilisateur" do
            if @login.text.empty? || @color.text.empty? || @sector.text.empty? ||
               @editor.text.empty? || @name.text.empty?
              _error 201
            elsif !(@login.text =~ /[a-zA-Z0-9_-]+/)
              _error 202, @login.text
            elsif File.exist?("./users/#{@login.text}") && File.directory?("./users/#{@login.text}")
              _error 203, @login.text
            elsif !File.exist?(@editor.text) || !File.executable?(@editor.text)
              _error 204, @editor.text
            else
              SedUser.create(@login.text, 
                :name   => @name.text,
                :color  => @color.text,
                :sector => @sector.text.upcase,
                :editor => @editor.text
              )
              alert("Compte créé avec succès, redirection vers la page utilisateur.")
              _userpage(@login.text)
            end
          end
        end
        
        # Little fix for design :/
        stack(:margin => 10){}
        
      end
      para link("Retour à la page d'accueil") { _index }
    end
  end
  
  def _userpage(login)
    @seduser = SedUser.new(login)
    if !@p_colors.keys.include?(@seduser.color) 
      _error(300, user.color) { _index } 
      return
    end
    _header(:background => @p_colors[@seduser.color], :user => @seduser)
    @contents.clear do
      flow :margin => 10 do
        stack :width => 0.15, :margin => 5 do
          para '  ', link("Propas") { _userpropas }, :margin => 5
          para '  ', link("Todos") { _usertodos }, :margin => 5
          para '  ', link("Déconnecter", :stroke => red, :font => '10px') {
            @seduser.save!
            @seduser = nil
            _index
          }, :margin => 5
        end
        @usergui = flow :width => 0.85, :margin => 5 do
          background '#999', :radius => 8
        end
        _usertodos
      end
    end
  end
  
  def _userpropas
    @usergui.clear do
      _page_header("Propagandes")
    end
  end
  
  def _usertodos
    @usergui.clear do
      _page_header("Liste de tâches")
      
      @todos = stack :margin => 10 do
        flow :margin => 5 do
          @add = edit_line
          button "OK" do
            if @add.text.empty?
              _error 200
            else
              @seduser.todo_add(@add.text)
              @todos.append { _todo_para(@add.text) }
              @seduser.todo_dump!
              @add.text = ''
            end
          end
        end
      end
      
      @seduser.todos.each {|t| @todos.append { _todo_para(t) } }
    end
  end
  
  # Default layout
  @body = stack do
    @header   = stack {}
    @contents = stack {}
  end
  
  # Initialization
  _header
  _index()

end
