# $Id: generator.rb,v 1.14 2004/04/27 16:12:31 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/wikitext'

module Qwik
  class PageGenerator # abstract class
    def initialize(config, memory)
      @config = config
      @memory = memory
      @data = {}
      @g = Qxhtml.new
    end

    def []=(k, v)
      @data[k] = v
    end

    def generate
      @xml.apply(@data)
      @xml.delete_empty_tag('div', 'span', 'pre')
      @xml.delete_id
      @xml.add_html_doctype
#      @xml.add_xhtml_doctype
      @xml
    end

    private
    def header(site, pagename)
      head = @g.head
      head << @g.make(:title){site.title(pagename)}
      stylesheets(site).each {|css|
	head << @g.stylesheet(css)
      }
      head
    end

    def get_template(cmd)
      @memory.template.get(cmd)
    end

    def get_themes(t)
      @memory.theme.get_themes(t)
    end
  end

  class ViewPageGenerator < PageGenerator
    def initialize(config, memory)
      super
      @xml = get_template('view')
    end

    def set_data(site, pagename)
      @data[:header]     = header(site, pagename)
      @data[:sidemenu]   = site[@config.sidemenu].load.w.res(site)
      @data[:topmenu]    = site[@config.topmenu ].load.w.res(site)
      @data[:title]      = site.title(pagename)
      page = site[pagename]
      @data[:view_title] = page.get_title
      @data[:body]       = page.load.w.tdiary_res(site)
      @data[:page_attribute] = site[@config.pagefooter].load.w.res(site)
    end

    private
    def stylesheets(site)
      t = site.config[:theme]
      t = @config.default_theme if t.nil?
      get_themes(t)
#      ["/theme/base.css", "/theme/#{t}/#{t}.css"]
    end
  end

  class SystemPageGenerator < PageGenerator # abstract
    def initialize(config, memory)
      super
      @xml = get_template('system')
    end

    private
    def header(site, pagename)
      head = super
      head << @g.meta(:name=>"ROBOTS", :content=>"NOINDEX,NOFOLLOW")
      head
    end

    def stylesheets(site=nil)
      get_themes("qwiksystem")
#      ["/theme/base.css", "/theme/qwiksystem/qwiksystem.css"]
    end
  end

  class EditPageGenerator < SystemPageGenerator
    def set_data(site, pagename)
      @data[:header]     = header(site, pagename)
      @data[:formupdate] = REXML::Attr.new(:action => pagename+'.html')
      @data[:view_title] = site.title(pagename)
      @data[:editorfooter] = site[@config.editorfooter].load.w.res(site)
#          <div id="link">最新版を参照: [<span id="linkp"></span>]</div>
    end
  end

  class MessagePageGenerator < SystemPageGenerator
    def generate
      @data[:header] = header
      super
      @xml.delete_empty_tag('input', 'textarea')
      @xml
    end

    private
    def header
      head = @g.head
      head << @g.make(:title){@data[:view_title]}
      stylesheets().each {|css|
	head << @g.stylesheet(css)
      }
      head
    end
  end

  class DiffHtmlGenerator
    def initialize(s1, s2)
      @s1 = s1.gsub(/\r/, '')
      @s2 = s2.gsub(/\r/, '')
    end

    def to_txt
      a1 = @s1.split("\n").collect! {|s| "#{s}\n"}
      a2 = @s2.split("\n").collect! {|s| "#{s}\n"}
      Diff.diff(a1, a2) 
    end

    def to_html
      text = ''
      src = @s1.split("\n").collect {|s| "#{s.escapeHTML}" }
      si = 0
      di = 0
      to_txt().each {|action,position,elements|
        case action
        when :-
          while si < position
            text << "#{src[si]} <br>"
            si += 1
            di += 1
          end
          si += elements.length
          elements.each do |l|
            text << "<del class=deleted>#{l}</del>"
          end
        when :+
          while di < position
            text << "#{src[si]} <br>"
            si += 1
            di += 1
          end
          di += elements.length
          elements.each do |l|
            text << "<ins class=added>#{l}</ins>"
          end
        end
      }
      while si < src.length
        text << "#{src[si]} <br>"
        si += 1
      end
      text
    end
  end

  class ServerMemory
    def template
      @template = TemplateFactory.new(@config) if @template.nil?
      @template
    end

    def theme
      @theme = ThemeFactory.new(@config) if @theme.nil?
      @theme
    end
  end

  class TemplateFactory
    def initialize(config)
      @config = config
      @templates = {}
    end

    def get(cmd)
      @templates[cmd] = xml(cmd) if @templates[cmd].nil?
      @templates[cmd].deep_clone
    end

    private
    def xml(cmd)
      str = open(path(cmd)){|f| f.read }
      str2 = ""
      str.each_line {|line|
	str2 << line.sub(/^\s+/, '')
      }
      str = str2.gsub(/\n/, '')
      xml = REXML::QDocument.new(str)
    end

    def path(cmd)
      path = @config.template_dir
      f = path+"/#{cmd}.html"
      return f if test(?e, f)
      return path+"/view.html"
    end
  end

  class Plugin
    def theme_list
      ar = @memory.theme.get_list
      e = @g.ul
      ar.each {|t|
	e << @g.li{t}
      }
      e
    end
  end

  class ThemeFactory
    def initialize(config)
      @config = config
      @theme_path = @config.theme_dir.path
    end

    def get_themes(t)
      ar = []
      ar << "/theme/base.css"
      ar << "/theme/#{t}/#{t}.css"
      ar
    end

    def get_list
      @themes = []
      @theme_path.each_entry {|d|
	dir = @theme_path+d
	next unless dir.directory?
	s = d.to_s
	next if s =~ /^\./
	next if s =~ /^CVS/
	@themes << d.to_s
      }
      @themes
    end

    private
    def get_theme(t)
      @theme_path
      
      str = open(path(cmd)){|f| f.read }
      str2 = ""
      str.each_line {|line|
	str2 << line.sub(/^\s+/, '')
      }
      str = str2.gsub(/\n/, '')
      xml = REXML::QDocument.new(str)
    end
  end
end
