class PagesController < ApplicationController
  
  before_filter :authenticate, :except => [:view]
  before_filter :authenticate_cadmin, :only => [:destroy]
  
  caches_page :view
  
  #--
  # TODO check that we really need this
  #++
  cache_sweeper :sweeper, :only => [:checkout, :checkin, :undocheckout, :destroy, :discussion]
  
  layout 'wiki'
  
  FLASH_CHECKIN_SUCCESS = "Check-in succesfull, please add or update the version note!"

  def view
    #--
    # TODO add 'Compare with previous' link
    #++ 
    logger.debug("params[:url]:" + params[:url])
    s3,s4,s5 = params[:url].split('/').values_at(2,3,4)
    @rel_path = params[:url].sub("http://#{s3}/#{s4}/#{s5}/", '').split('?')[0] # url sometimes contains a parameter! 
    logger.debug("Finding wiki by folder #{s4}")
    @wiki = Wiki.find_by_folder(s5)
    @page = WikiPage.find_by_rel_path_and_site_id(@rel_path, @wiki.id)
    if @page
      logger.debug("Page found")
      @version = @page.current_version 
      @comments = Comment.find(:all, :conditions => ["page_id=? and site_id=?", @page.id, @wiki.id], :order => 'created_on ASC') 
      @checkout = @page.checkout
      logger.debug("@version: #{@version.inspect}")
      @contributor_names = @page.contributors
    end

    @checkout_text = "This page is currently being created or modified by #{@checkout.user.name}" if @checkout and @version
     
    respond_to do |format|
      format.js 
    end
  end

  def discussion
    if request.get?
      @wiki = Wiki.find_by_folder(params[:site_folder]) 
      @page = Page.find(params[:id])
      @comment = Comment.new(:site => @wiki, :page => @page) 
    else
      @comment = Comment.new(params[:comment].merge(:user => session_user))
      @page = @comment.page
      @wiki = @page.site 
      @comment.version = @page.current_version
      if @comment.save
        redirect_to :controller => 'pages', :site_folder => @wiki.folder, :id => @page.id, :action => 'discussion'
        users = (User.find(:all, :conditions => ['notify_immediate=?', 1]) + Notification.find_all_users(@page, Page.name)).uniq
        users += Notification.find_all_users(@wiki, 'Immediate')          
        unless users.empty?
          subject = "New comment about #{@page.presentation_name}"
          introduction = "User #{@comment.user.name} created a comment about <a href=\"#{@comment.page.url(true, request.host + (request.port == 80 ? '' : ':' + request.port.to_s))}\">#{@comment.page.presentation_name}</a> in site #{@comment.site.title}<br>"
          Notifier.notification(users.uniq,subject,introduction, @comment.text, request.host + (request.port == 80 ? '' : ':' + request.port.to_s)).deliver
        end
      end
    end
    @comments = Comment.find(:all, :conditions => ["page_id=? and site_id=?", @page.id, @wiki.id], :order => 'created_on ASC') 
  end

  def edit
    if params[:checkout_id]
      @checkout = Checkout.find(params[:checkout_id])
      v0 = @checkout.version.previous_version 
      if v0.version == 0
        unless File.exists? v0.path(true) # we also want version 0 in TinyMCE format
          h = v0.html
          h = h.gsub(Page::BODY_TAG_PATTERN, '<body>') 
          h = h.gsub(Page::TREEBROWSER_PATTERN, Page::TREEBROWSER_PLACEHOLDER)
          h = h.gsub(Page::HEAD_PATTERN, '')
          @version0_html = h
        end
      end
      @page = @checkout.page 
      @wiki = @checkout.site
      render :layout => false
    else
      redirect_to :action => 'checkout', :id => params[:id], :site_folder => params[:site_folder]
    end
  end
  
  # Action #checkout to create a new checkout 
  def checkout
    if request.get?
      @version = UserVersion.new
      @page = Page.find(params[:id])
      @wiki = @page.site
      #--
      #@wiki = Wiki.find_by_folder(params[:site_folder]) 
      # TODO these kind of statement are no longer necessary, 
      # do global search and replace
      #++
      @version.wiki = @wiki
      co = @page.checkout 
      if co
        redirect_to :action => 'edit', :checkout_id => co.id
      else
        @version.source_version = @page.current_version
      end
    else
      logger.info("Creating new checkout using params #{params[:user_version].inspect}")
      @version = UserVersion.new(params[:user_version]) 
      @version.source_version = Version.find(@version.version_id) # TODO
      @page = @version.source_version.page
      @wiki = @page.site
      co = Checkout.new(:note => @version.note, :page => @page, :site => @wiki, :source_version => @version.source_version, :user => session_user, :version => @version )
      if co.save
        redirect_to :action => 'edit', :checkout_id => co.id 
      else
        logger.info("Failed to save checkout #{co.inspect}")
      end
    end
    @versions = @page.versions
  end

  # #save the HTML after checking that the User is the owner. The Page remains checked-out.
  def save
    @checkout = Checkout.find(params[:checkout_id])
    raise LoginController::FLASH_UNOT_CADMIN if !mine?(@checkout) && !cadmin?
    @checkout.version.html = params[:html]
    if params[:html_v0] # will only be present when previous version is version 0
      @version0 = @checkout.version.previous_version
      @version0.save_tinymce_html(params[:html_v0])    
    end
    @checkout.version.save
    if params[:action] == 'save'
      redirect_to :action => 'edit', :checkout_id => @checkout.id
    else
      redirect_to(url_for('/' + @checkout.version.rel_path_root))    
    end
  end
  
  def preview
    save
  end
  
  # Action #checkin to checkin a page that is checked-out
  # TODO force post method
  def checkin
    if params[:checkout_id]
      logger.info("Finding checkout with id #{params[:checkout_id]}")
      co = Checkout.find(params[:checkout_id])
      @version = co.version
      @wiki = co.site
      @page = co.page
      co.checkin(session_user, params[:html]) # will create Notification record
      if params[:html_v0] # will only be present when previous version is version 0
        @version0 = co.version.previous_version
        @version0.save_tinymce_html(params[:html_v0])    
      end      
      raise "Failed to checkin #{checkout.id}" if Checkout.exists?(co.id)
      flash.now['success'] = FLASH_CHECKIN_SUCCESS
      users = (User.find(:all, :conditions => ['notify_immediate=?', 1]) + Notification.find_all_users(@page, Page.name)).uniq
      users += Notification.find_all_users(@wiki, 'Immediate')
      unless users.empty?
          subject = "New version created of #{@version.page.presentation_name}"
          introduction = "User #{@version.user.name} created a version of <a href=\"#{@version.page.url(true, request.host + (request.port == 80 ? '' : ':' + request.port.to_s))}\">#{@version.page.presentation_name}</a> in site #{@version.wiki.title}<br>"
          Notifier.notification(users.uniq,subject,introduction, @version.note, request.host + (request.port == 80 ? '' : ':' + request.port.to_s)).deliver
      end
      #redirect_to :controller => 'versions', :action => 'edit', :id => version.id
      if @version.template?
        # Because we use note field to cache the brief description of a template
        # the field should be empty. # TODO Maybe we should rethink this use of the note field
        @version.note = ''
        @version.save!
        redirect_to '/' + @version.wiki.rel_path + '/' + @version.page.rel_path
      end
    else
      logger.debug("Updating version note using params #{params.inspect}")
      @version = Version.find(params[:version][:id])
      @wiki = @version.wiki
      @page = @version.page
      if mine?(@version) || cadmin?
        #@version.note = params[:version][:note]
        if @version.update_attributes(params[:version])
          flash['notice'] = Utils::FLASH_RECORD_UPDATED # TODO test this
          #redirect_to :action => 'list', :site_id => @version.site_id, :page_id => @version.page_id
          redirect_to '/' + @version.wiki.rel_path + '/' + @version.page.rel_path
        end    
      else
        flash.now['error'] = Utils::FLASH_NOT_OWNER # TODO test this
      end
    end
  end

  # Action #new to create a new Page based on a template or based on another page.
  def new
    @wiki = Wiki.find_by_folder(params[:site_folder])
    @page = Page.find(params[:id])
    @page_version = @page.current_version
    if  request.get?
      @new_page = Page.new
      @new_page.source_version = @page_version.id if @page_version # TODO a better name would be source_version_id?
    else
      logger.info("Creating new page with #{params.inspect}")
      #@templates = []
      version = nil
      version = Version.find(params[:page][:source_version]) if params[:page][:source_version]  
      @new_page, @checkout = WikiPage.new_using_template(params[:page].merge(:user=> session_user, :site => @wiki, :source_version => version))
      if @new_page.errors.empty?
        if @new_page.save
          if @checkout
            redirect_to :action => 'edit', :checkout_id => @checkout.id
          end
        end
      else
        logger.info("New page has errors: #{@new_page.errors.full_messages.join(', ')}")
      end
    end
    @templates = Site.templates
    @templates = ([@page_version] + @templates).compact.uniq # compact because @page_version can be nil
  end
  
  #--
  # TODO improved security - move authorisation check to Checkout.undo?
  #++
  def undocheckout
    co = Checkout.find(params[:checkout_id])
    page = co.page
    wiki = co.site
    if mine?(co) || cadmin?
      co.undo
      if  Checkout.exists?(co.id)
        raise "Failed to undo checkout #{co.id} of page #{co.page.presentation_name}"
      else
        if Page.exists?(page.id)
          redirect_to page.url
        else
          redirect_to wiki.pages[0].url
        end
      end
    else
      raise "This checkout is owned by #{co.user.name}. You cannot undo a checkout that belongs to another user"
    end
  end
  
  # TODO  Implement test
  def destroy 
    @page = Page.find(params[:id])
    #paths.each {|path| File.delete(path) if File.exists?(path)} # decided not to delete the files
    Checkout.destroy_all(['page_id=?', @page.id])
    Comment.destroy_all(['page_id=?', @page.id])
    Notification.destroy_all(['page_id=?', @page.id])
    Version.destroy_all(['page_id=?', @page.id])
    @page.destroy
    flash['success'] = "Page #{@page.presentation_name}deleted!"
    redirect_to request.referer
  end
  
  def history # TODO test
    @page = Page.find(params[:id])
    @wiki = Wiki.find_by_folder(params[:site_folder])
    @versions = @page.versions
    @versions << @page.checkout.version unless @page.checkout.nil?
    @other_versions = Version.find(:all, :conditions => ['wiki_id<>? and page_id=?', @wiki.id, @page.id], :order=> 'wiki_id, version ASC')
  end

  def rollback
    unless params[:version].nil?
      to = Version.find(params[:version][:version_id])
      if to.page.checkout.nil?
        co = Checkout.new(:user => session_user, :page => to.page, :site => to.wiki, :source_version => to, :note => "Rollback to version #{to.version}")
        if co.save
          co.checkin(session_user)
          flash['success'] = 'Rollback complete'
        else
          flash['error'] = 'Rollback failed'
        end
      else
        flash['error'] = 'Cannot rollback checked out page'
      end
      redirect_to :action => 'history', :id => to.page.id, :site_folder => to.wiki.folder
    end
  end

  def text
    @page = Page.find(params[:id])
    render :inline => "<%= (simple_format(strip_tags(@page.html))) %>", :layout => false
  end
  
  # TODO be able to quickly retrieve a list of pages based on content type in a site
  #def list
  #  sidebar
  #  uma_type = params[:type].capitalize.singularize
  #  logger.info("Selecting pages with uma_type #{uma_type}")
  #  @pages = Page.find(:all, :order => 'presentation_name ASC', :conditions => ['uma_type=?', uma_type])
  #   render :layout => 'application'
  #end
  
end
