# $Id: command.rb,v 1.17 2004/04/28 13:17:58 eto Exp $
# Copyright (C) 2003-2004 Kouichirou Eto, All rights reserved.
# This is free software with ABSOLUTELY NO WARRANTY.
# You can redistribute it and/or modify it under the terms of the GNU GPL2.

require "qwik/parser"
require 'qwik/util'
require 'qwik/site'
require 'qwik/diff'
require 'qwik/generator'
require 'qwik/extension'

module Qwik
  class CommandExecutor
    def initialize(session)
      @session = session
      @config  = @session.config
      @memory  = @session.memory
      @req     = @session.req
      @res     = @session.res
      @site    = @session.site
      @pagename = @req.base
      @page = @site[@pagename]
      options = Hash.new('')
      options['memory']   = @memory
      options['pagename'] = @pagename
      options['page']     = @page
      options['site']     = @site
      options['req']      = @req
      options['res']      = @res
      @plugin = Plugin.new(@config, options)
      @site.plugin = @plugin
      @g = Qxhtml.new
    end

    def dispatch
      if @pagename == '_new'
	return cmd_new
      end

      cmd = @req.query['c']
      if cmd.nil? || cmd == 'view'
	return page_not_found() if @page.nil?
	return page_view() 
      end
      case cmd
      when 'edit'
	cmd_edit
      when 'save'
	cmd_save
      else
	raise
      end
    end

    private

    def page_view
      gen = ViewPageGenerator.new(@config, @memory)
      gen.set_data(@site, @pagename)
      gen.generate
    end

    def page_not_found
      gen = MessagePageGenerator.new(@config, @memory)
      gen[:view_title] = 'ページが見つかりません'
      gen[:msg] = "ページが見つかりません．"
      gen.generate
    end

    def cmd_edit(contents=nil, msg=nil, differ=nil)
      gen = EditPageGenerator.new(@config, @memory)
      gen.set_data(@site, @pagename)
      gen[:msg] = msg if msg
      gen[:differ] = differ
      if contents
	str = contents
      else
	str = @page.load
      end
      gen[:contents] = str
      gen[:md5hex]   = REXML::Attr.new(:value => str.md5hex)
      gen.generate
    end

    def page_conflict(contents=nil, msg=nil)
      differ = DiffHtmlGenerator.new(contents, @page.load).to_html
      cmd_edit(contents, msg, differ)
    end

    def cmd_save()
      contents = @req.query['contents']

      # cannot delete a page with password
      if contents.size == 0 && !@page.have_password?
	return page_delete()
      end

      newcontents = @page.embed_password(contents) # embed the password
      if !@page.match_password?(newcontents)
	return cmd_edit(contents, "パスワードが一致しませんでした。")
      end
      contents = newcontents

      contents = contents.gsub(/\r/, '')
      begin
	@page.store(contents, @md5hex) # with side effect
      rescue PageCollisionError # failed to save?
	return page_conflict(contents, '更新が衝突しました。下記の内容をテキストエディタなどに保存し、最新のページを参照後に再編集してください。')
      end

#      redirect(@pagename+".html")

      gen = MessagePageGenerator.new(@config, @memory)
      gen[:view_title] = 'ページを保存しました'
      g = Qxhtml.new
      gen[:msg] = g.div{[
	  g.p{'ページを保存しました。'},
	  g.p{[g.a(@pagename+".html"){'最新のページ'}, 'に飛ぶ。']}
	]}
      gen.generate
    end

#    def redirect(file)
#      return # I don't use redirect for now.
#      @res.status = 302
#      @res['Location'] = @site.url+file
#      @res['Location'] = file if @req.localmode
#    end

    def page_delete()
      @site.pages.delete(@pagename) # DELETE
      gen = MessagePageGenerator.new(@config, @memory)
      gen[:view_title] = 'ページを削除しました'
      gen[:msg] = @g.div{[
	  @g.p{'ページを削除しました。'},
	  @g.p{[@g.a(@config.frontpage+".html"){'トップページ'}, 'に戻る。']}
	]}
      gen.generate
    end

    def cmd_new()
      frompagename = @req.query['f'] # stands for 'from'
      newpagetitle = @req.query['t']
      newpagename = @site.pages.get_new_id
      page = @site.create(newpagename) # CREATE
      if newpagetitle
	page.store("* #{newpagetitle}\n") # at the first, make the page with the title.
	if frompagename
	  str = @site[frompagename].load # change the from page
	  if str =~ /\[\[(.+)\|#{newpagetitle}\]\]/
	    str.gsub!(/\[\[(.+)\|#{newpagetitle}\]\]/){|g|
	      "[[#{$1}|#{newpagename}]]"
	    }
	  else
	    str.gsub!(/\[\[#{newpagetitle}\]\]/, "[[#{newpagetitle}|#{newpagename}]]")
	  end
	  begin
	    @site[frompagename].store(str) # STORE
	  rescue PageCollisionError # failed to save?
	    # FIX: do nothing
	  end
	end
      else
	page.store("") # make a null page
      end

      newpagehref = newpagename+".html?c=edit"

#      redirect(newpagehref)

      gen = MessagePageGenerator.new(@config, @memory)
      gen[:view_title] = '新規ページを作成しました'
      g = Qxhtml.new
      gen[:msg]   = g.div{[
	  g.p{'新規ページを作成しました'},
	  g.p{[g.a(newpagehref){'新規ページを編集'}, 'してください。']}
	]}
      gen.generate
    end
  end
end
