# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/act-password"
require "qwik/wabisabi-diff"
require "qwik/act-editor"

module Qwik
  class Action
    def ext_edit
      c_require_login
      c_require_page_exist
      generate_edit_page
    end

    def generate_edit_page(contents=nil, message=nil)
      #c_monitor("startedit")
      c_editor(@site, @req.base, contents, message)
    end

    def ext_save(contents=nil)
      c_require_login
      c_require_page_exist

      contents = @req.query["contents"] if contents.nil?
      raise "contents is nil." if contents.nil?

      page = @site[@req.base]
      # cannot delete a page with password
      if contents.size == 0 && !page.have_password?
	@site.delete(@req.base) # DELETE
	c_make_log("delete") # DELETE
	c_monitor("delete") # DELETE
	return save_page_deleted
      end

      newcontents = page.embed_password(contents) # embed the password
      if !page.match_password?(newcontents)
	return save_password_does_not_match(contents)
      end
      contents = newcontents

      contents = contents.gsub(/\r/, "")
      md5hex = @req.query["md5hex"]
      md5hex = nil if page.have_password?
      begin
	#qp contents, md5hex
	page.store(contents, md5hex) # STORE
      rescue PageCollisionError # failed to save?

	pagename = @req.base
	page = @site[pagename]
	differ = DiffGenerator.generate(contents, page.load)

	return save_edit_conflict(pagename, differ, contents)
      end

      c_make_log("save") # STORE
      c_monitor("save") # STORE

      url = @req.base+".html"
      return save_page_is_saved(url)
    end

    def save_page_deleted
      c_notice(_("Page is deleted."), "FrontPage.html"){[
	  [:h2, _("Page is deleted.")],
	  [:p,_("Go next")," : ",[:a,{:href=>"FrontPage.html"},"FrontPage.html"]],
	]}
    end

    def save_password_does_not_match(contents)
      message = [:div, {:class=>"day"},
	[:h2, _("Password does not match.")],
	[:div, {:class=>"section"},
	  [:p, [:tt, "{{password("], _("Password"), [:tt, ")}}"]],
	  [:p, _("Please find a line like above, then input password in parentheses.")],
	]
      ]
      generate_edit_page(contents, message)
    end

    def save_edit_conflict(pagename, differ, contents)
      message = [:div, {:class=>"day"},
	[:h2, _("Page edit conflict")],
	[:div, {:class=>"section"},
	  [:p, _("Please save the following content to your text editor."),
	    [:a, {:href=>pagename+".html"}, _("Newest page")],
	    _(": see this page and re-edit again.")]],
	[:div, {:class=>"differ"},
	  differ]]
      generate_edit_page(contents, message)
    end

    def save_page_is_saved(url)
      c_notice(_("Page is saved."), url){[
	  [:h2, _("Page is saved.")],
	  [:p,_("Go next")," : ",[:a,{:href=>url},url]],
	]}
    end

  end
end

if $0 == __FILE__
  require "t/test"
  $debug = true
end

if $debug
  class TC_ActEdit < Test::Unit::TestCase
    include TestSession

    def test_save
      t_add_user

      # create a page
      session("POST /test/.new?t=TestPage")
      assert_xpath([:a, {:href=>"TestPage.edit"}, "Edit new page"],
		   "//div[@class='section']/a")

      session("/test/TestPage.edit")
      assert_text("Edit | TestPage", "title")
      assert_text("* TestPage\n", "textarea")

      # try to save a page that is not exist.
      session("/test/NoSuchPage.save?contents=t")
      assert_equal(404, @res.status)
      assert_text("Page not found.", "h1")

      # save a page
      session("/test/TestPage.save?contents=t")
      assert_text("Page is saved.", "title")
      assert_text("Page is saved.", "h1")
      assert_equal("t", @site["TestPage"].load)

      # delete the page
      session("/test/TestPage.save?contents=") # null content
      assert_text("Page is deleted.", "title")

      # Try to delete again.
      session("/test/TestPage.save?contents=") # null content
      assert_text("Page not found.", "title")

      # ------------------------------
      # test_save_again
      page = @site.create_new
      page.store("* t")
      session("/test/1.edit") # see an edit page
      assert_text("Edit | t", "title")
      assert_text("Edit | t", "h1")
      assert_text("* t", "textarea")

      # save it
      session("/test/1.save?contents=* t%0A* h2 of 2%0Ah22body%0A")
      assert_text("Page is saved.", "title")
      assert_text("Page is saved.", "h1")

      # see the result
      session("/test/1.html")
      assert_text("t", "h1")
      #px("//div[@class='day'][2]/h2", 0)
      #px("//div[@class='day']", 0)
      #px("//div[@class='main']", 0)
      #assert_xml("h2 of 2", "//div[@class='day'][3]/h2")

      # ------------------------------
      # test_save_new_delete

      # see a page
      session("/test/")
      assert_text("FrontPage", "title")

      # see an edit screen of the page
      session("/test/FrontPage.edit")
      assert_text("Edit | FrontPage", "title")
      assert_attr({"action"=>"FrontPage.save", "method"=>"POST"}, "form")
      assert_xml(/^\* FrontPage/, "//textarea")
      assert_xpath([:input, {:value=>"dae58ef7afd29544c7196b4cbde04902",
		     :type=>"hidden",  :name=>"md5hex"}], "//input")
      e = @res.body.get_path("//input")
      md5hex = e[1][:value]
      assert_equal("dae58ef7afd29544c7196b4cbde04902", md5hex)
      assert_attr({"name"=>"save", "type"=>"submit", "value"=>"Save"},
		  "input[2]")

      # save it
      session("/test/FrontPage.save?md5hex=#{md5hex}&save=Save&contents=* FrontPage%0A[[test]]%0A")
      assert_text("Page is saved.", "title")
      assert_text("Page is saved.", "h1")
      assert_attr({"href"=>"FrontPage.html"}, "a")

      # see the result, and the page contains a link to new page.
      session("/test/")
      assert_xml("test", "//div[@class='section']//span")
      assert_rattr({"class"=>"new"}, "//div[@class='section']//span")
      assert_rattr({"href"=>".new?t=test", "class"=>"new"},
		   "//div[@class='section']//a")
      assert_xpath([:a, {:href=>".new?t=test", :class=>"new"},
		     [:img, {:alt=>"create", :class=>"new",
			 :src=>"/.theme/i/new.png"}]],
		   "//div[@class='section']//a")

      # create a new page.
      session("POST /test/.new?t=test")
      assert_text("New page", "title")
      assert_text("New page", "h1")
      assert_xpath([:a, {:href=>"test.edit"}, "Edit new page"],
		   "//div[@class='section']//a")
      assert_equal("* test\n", @site["test"].load)

      # see the from page
      session("/test/")
      assert_xpath([:a, {:href=>"test.html"}, "test"],
		   "//div[@class='section']//a")

      # try to see a page that does not exist.
      session("/test/nosuchpage.html")
      assert_equal(404, @res.status)
      assert_text("Page not found.", "title")
      assert_text("Page not found.", "h1")

      # try to edit a page that does not exist.
      session("/test/nosuchpage.edit")
      assert_text("Page not found.", "title")

      # see the edit screen of the new page
      session("/test/test.edit")
      assert_text("* test\n", "textarea")
      assert_attr({"name"=>"md5hex", "type"=>"hidden",
		    "value"=>"2f1580c9dc650a5d827ba7bf44be031b"}, "input")
      md5hex = "2f1580c9dc650a5d827ba7bf44be031b"

      # delete the new page
      session("/test/FrontPage.save?md5hex=#{md5hex}&save=Save&contents=")
      assert_text("Page is deleted.", "title")
      assert_text("Page is deleted.", "h1")
    end

    def test_conflict
      t_add_user

      page = @site.create_new
      page.store("t1")

      # See the page
      session("/test/1.html")
      assert_xpath([:p, "t1"], "//div[@class='section']/p")

      # See editor.
      session("/test/1.edit")
      assert_xpath([:textarea, {:id=>"contents", :name=>"contents",
		       :cols=>"70", :rows=>"20"}, "t1"], "//textarea")
      assert_xpath([:input, {:value=>"83f1535f99ab0bf4e9d02dfd85d3e3f7",
		       :type=>"hidden", :name=>"md5hex"}], "//input")
      assert_xpath([:input, {:value=>"Save", :type=>"submit", :name=>"save"}],
		   "//input[2]")

      # Save.
      session("/test/1.save?contents=t2&md5hex=83f1535f99ab0bf4e9d02dfd85d3e3f7")
      assert_text("Page is saved.", "title")
      assert_equal("t2", page.load)

      # See editor again.
      session("/test/1.edit")
      assert_xpath([:textarea, {:id=>"contents", :name=>"contents",
		       :cols=>"70", :rows=>"20"}, "t2"], "//textarea")
      assert_xpath([:input, {:value=>"0f826a89cf68c399c5f4cf320c1a5842",
		       :type=>"hidden", :name=>"md5hex"}], "//input")

      # But in this moment, another person rewrite the page.
      page.store("t3")

      # Try to save again, but failed.
      session("/test/1.save?contents=t4&md5hex=0f826a89cf68c399c5f4cf320c1a5842")
      assert_text("Edit | 1", "title")
      assert_in(["Page edit conflict"], "//div[@class='message']/h2")
      assert_in(["Please save the following content to your text editor.",
		  [:a, {:href=>"1.html"}, "Newest page"],
		  ": see this page and re-edit again."],
		"//div[@class='message']/p")
      assert_in([[:del, "t4"], [:br], [:ins, "t3"], [:br]],
		"//div[@class='differ']")
      assert_equal("t3", page.load)
    end

  end
end
