#!/usr/bin/env ruby

$:.unshift File.dirname(__FILE__) + "/../../lib"
require 'camping'
require 'camping/db'
require 'camping/session'
  
Camping.goes :Blog

module Blog
    include Camping::Session
end

module Blog::Models
    class Post < Base; belongs_to :user; end
    class Comment < Base; belongs_to :user; end
    class User < Base; end

    class CreateTheBasics < V 1.0
      def self.up
        create_table :blog_posts do |t|
          t.column :user_id,  :integer, :null => false
          t.column :title,    :string,  :limit => 255
          t.column :body,     :text
        end
        create_table :blog_users do |t|
          t.column :username, :string
          t.column :password, :string
        end
        create_table :blog_comments do |t|
          t.column :post_id,  :integer, :null => false
          t.column :username, :string
          t.column :body,     :text
        end
        User.create :username => 'admin', :password => 'camping'
      end
      def self.down
        drop_table :blog_posts
        drop_table :blog_users
        drop_table :blog_comments
      end
    end
end

module Blog::Controllers
    class Index < R '/'
        def get
            @posts = Post.find :all
            render :index
        end
    end
     
    class Add
        def get
            unless @state.user_id.blank?
                @user = User.find @state.user_id
                @post = Post.new
            end
            render :add
        end
        def post
            unless @state.user_id.blank?
                post = Post.create :title => input.post_title, :body => input.post_body,
                                   :user_id => @state.user_id
                redirect View, post
            end
        end
    end

    class Info < R '/info/(\d+)', '/info/(\w+)/(\d+)', '/info', '/info/(\d+)/(\d+)/(\d+)/([\w-]+)'
        def get(*args)
            div do
                code args.inspect; br; br
                code @env.inspect; br
                code "Link: #{R(Info, 1, 2)}"
            end
        end
    end

    class View < R '/view/(\d+)'
        def get post_id 
            @post = Post.find post_id
            @comments = Models::Comment.find :all, :conditions => ['post_id = ?', post_id]
            render :view
        end
    end
     
    class Edit < R '/edit/(\d+)', '/edit'
        def get post_id 
            unless @state.user_id.blank?
                @user = User.find @state.user_id
            end
            @post = Post.find post_id
            render :edit
        end
     
        def post
            unless @state.user_id.blank?
                @post = Post.find input.post_id
                @post.update_attributes :title => input.post_title, :body => input.post_body
                redirect View, @post
            end
        end
    end
     
    class Comment
        def post
            Models::Comment.create(:username => input.post_username,
                       :body => input.post_body, :post_id => input.post_id)
            redirect View, input.post_id
        end
    end
     
    class Login
        def post
            @user = User.find :first, :conditions => ['username = ? AND password = ?', input.username, input.password]
     
            if @user
                @login = 'login success !'
                @state.user_id = @user.id
            else
                @login = 'wrong user name or password'
            end
            render :login
        end
    end
     
    class Logout
        def get
            @state.user_id = nil
            render :logout
        end
    end
     
    class Style < R '/styles.css'
        def get
            @headers["Content-Type"] = "text/css; charset=utf-8"
            @body = %{
                body {
                    font-family: Utopia, Georga, serif;
                }
                h1.header {
                    background-color: #fef;
                    margin: 0; padding: 10px;
                }
                div.content {
                    padding: 10px;
                }
            }
        end
    end
end

module Blog::Views

    def layout
      html do
        head do
          title 'blog'
          link :rel => 'stylesheet', :type => 'text/css', 
               :href => '/styles.css', :media => 'screen'
        end
        body do
          h1.header { a 'blog', :href => R(Index) }
          div.content do
            self << yield
          end
        end
      end
    end

    def index
      if @posts.empty?
        p 'No posts found.'
        p { a 'Add', :href => R(Add) }
      else
        for post in @posts
          _post(post)
        end
      end
    end

    def login
      p { b @login }
      p { a 'Continue', :href => R(Add) }
    end

    def logout
      p "You have been logged out."
      p { a 'Continue', :href => R(Index) }
    end

    def add
      if @user
        _form(@post, :action => R(Add))
      else
        _login
      end
    end

    def edit
      if @user
        _form(@post, :action => R(Edit))
      else
        _login
      end
    end

    def view
        _post(@post)

        p "Comment for this post:"
        for c in @comments
          h1 c.username
          p c.body
        end

        form :action => R(Comment), :method => 'post' do
          label 'Name', :for => 'post_username'; br
          input :name => 'post_username', :type => 'text'; br
          label 'Comment', :for => 'post_body'; br
          textarea :name => 'post_body' do; end; br
          input :type => 'hidden', :name => 'post_id', :value => @post.id
          input :type => 'submit'
        end
    end

    # partials
    def _login
      form :action => R(Login), :method => 'post' do
        label 'Username', :for => 'username'; br
        input :name => 'username', :type => 'text'; br

        label 'Password', :for => 'password'; br
        input :name => 'password', :type => 'text'; br

        input :type => 'submit', :name => 'login', :value => 'Login'
      end
    end

    def _post(post)
      h1 post.title
      p post.body
      p do
        [a("Edit", :href => R(Edit, post)), a("View", :href => R(View, post))].join " | "
      end
    end

    def _form(post, opts)
      p { "You are logged in as #{@user.username} | #{a 'Logout', :href => R(Logout)}" }
      form({:method => 'post'}.merge(opts)) do
        label 'Title', :for => 'post_title'; br
        input :name => 'post_title', :type => 'text', 
              :value => post.title; br

        label 'Body', :for => 'post_body'; br
        textarea post.body, :name => 'post_body'; br

        input :type => 'hidden', :name => 'post_id', :value => post.id
        input :type => 'submit'
      end
    end
end
 
def Blog.create
    Camping::Models::Session.create_schema
    Blog::Models.create_schema :assume => (Blog::Models::Post.table_exists? ? 1.0 : 0.0)
end

