require "vizshot_gfdnavi"
require "pp"

Dependencies.require_or_load "execute_analysis"

class KnowledgeController < ApplicationController
  # ApplicationController < ActionController::Base (in application.rb)
  include ExecuteAnalysis

  layout "gfdnavi", :except => [:list_from_outside]
  before_filter :login_required, :except => [:index, :list, :show]

  def index
    list
    render :action => 'list'
  end

  verify :method => :post, :only => [ :destroy, :create, :update ], :redirect_to => { :action => :list }

  def list
    if Knowledge.respond_to?("paginate")
      # @knowledges = Knowledge.paginate(:all, {:user => session[:user]}, {:page => params[:page], :per_page => 5, :order=>"id"}).reverse
      @knowledges = Knowledge.paginate(:all, {:user => session[:user]}, {:page => params[:page], :per_page => 5, :order=>"knowledges.id DESC"})
    else
      @knowledge_pages, @knowledges = paginate :knowledges, :per_page => 5
      @knowledge = Knowledge.find(:all, :user => session[:user]).reverse
    end
  end

  def list_from_outside
    list
    render :action => 'list'
  end

  # list.rhtml -> show.rhtml (Click a title.)
  def show
    @knowledge = Knowledge.find(:first, :conditions => ["path=?", params[:path]], :user => session[:user])
    @knowledge_figures = KnowledgeFigure.find(:all, :conditions => ["knowledge_id=?", @knowledge.id])
  end

  # list.rhtml -> new.rhtml (Click "New Knowledge".)
  def new
    @type = "new"
    @knowledge = Knowledge.new
    @user_name = session[:user].login
    @groups = session[:user].belonging_groups

    session[:knowledge] = Hash.new
    session[:knowledge]["num_of_figure"] = 1
    session[:knowledge_figure] = Hash.new
    session[:knowledge_figure]["diagram_ids"] = Array.new
    session[:knowledge_figure]["figure_captions"] = Array.new
    session[:knowledge_figure]["diagram_paths"] = ["/images/white.bmp"]
  end

  def new_from_analysis
    @type = "new_from_analysis"
    @knowledge = Knowledge.new
    @groups = session[:user].belonging_groups
    @user_name = session[:user].login

    if(params["from_analysis"] == "from_analysis")
      session[:knowledge] = {"title" => "", "textbody" => "", "knowledge_path" => "", "default_layout" => "", "group_name" => ""}
      if (diagrams = session[:diagrams].dup)
        diagrams = diagrams.sort.collect{|i,dia| diagram_to_dginfo(dia)}
        diagram_paths = Array.new
        diagram_ids = Array.new
        if diagrams
          diagrams.each{|dia|
            diagram_paths.push(dia[1])
            diagram_ids.push(dia[2])
          }
        end
        session[:knowledge_figure] = Hash.new
        session[:knowledge_figure]["diagram_ids"] = diagram_ids
        session[:knowledge_figure]["diagram_paths"] = diagram_paths
        figure_captions = Array.new
        for i in 1 .. diagram_paths.length
          figure_captions.push("")
        end
        session[:knowledge_figure]["figure_captions"] = figure_captions
      else
        raise "diagram is not found."
      end
    else
      if session[:knowledge]
        @knowledge.title = session[:knowledge]["title"]
        @knowledge.textbody = session[:knowledge]["textbody"]
        @knowledge.node.path = session[:knowledge]["knowledge_path"]
        @knowledge.default_layout = session[:knowledge]["default_layout"]
        if session[:knowledge]["group_name"] == "everyone"
          @knowledge.group_id = nil
        else
          if group = Group.find(:first, :conditions => ["name = ? and user_id = ?", session[:knowledge]["group_name"], session[:user].id])
            @knowledge.group_id = group.id
          else
            # raise "Specified group is not found."
            @knowledge.group_id = nil
          end
        end
      else # (== new)
        session[:knowledge] = {"title" => "", "textbody" => "", "knowledge_path" => "", "default_layout" => "", "group_name" => "everyone"}
        session[:knowledge_figure] = Hash.new
        diagram_ids = Array.new
        diagram_paths = Array.new
        session[:knowledge_figure]["diagram_ids"] = diagram_ids
        session[:knowledge_figure]["diagram_paths"] = diagram_paths
        figure_captions = Array.new
        session[:knowledge_figure]["figure_captions"] = figure_captions
      end
    end
    
    if session[:knowledge_figure]["diagram_ids"]
      session[:knowledge]["num_of_figure"] = session[:knowledge_figure]["diagram_ids"].length
    else
      session[:knowledge]["num_of_figure"] = 0
    end

=begin
    print "session[knowledge_figure] = "
    pp session[:knowledge_figure]
    print "@type = "
    pp @type    
=end
  end

  def edit
    print "---- edit ----\nparams = "
    pp params

    @type = "edit"
    @groups = session[:user].belonging_groups

    # list.rhtml -> edit.rhtml (Click "Edit".)
    if params["from_list"] == "from_list"
      @knowledge = Knowledge.find(:first, :conditions => ["path=?", params[:path]], :user => session[:user])
      session[:knowledge] = Hash.new
      session[:knowledge_figure] = Hash.new
      session[:knowledge_figure]["diagram_ids"] = Array.new
      session[:knowledge_figure]["figure_captions"] = Array.new
      session[:knowledge_figure]["diagram_paths"] = Array.new
      knowledge_figures = @knowledge.knowledge_figures
#      print "knowledge_figures = "
#      pp knowledge_figures
      
      knowledge_figures.each do |kf|
        if kf.knowledge_id == @knowledge.id
          img = Image.find_by_sql("SELECT * FROM images WHERE id=#{kf.image_id}")[0]
          session[:knowledge_figure]["figure_captions"] << kf.caption
          session[:knowledge_figure]["diagram_paths"] << img.node.path
        end
      end
      # 
    elsif session[:knowledge]
      @knowledge = Knowledge.find_for_owner(session[:user], params[:id])
      @knowledge.title = session[:knowledge]["title"]
      @knowledge.textbody = session[:knowledge]["textbody"]
      @knowledge.node.path = session[:knowledge]["knowledge_path"]
      @knowledge.default_layout = session[:knowledge]["default_layout"]
      if session[:knowledge]["group_name"] == "everyone"
        @knowledge.group_id = nil
      else
        if group = Group.find(:first, :conditions => ["name = ? and user_id = ?", session[:knowledge]["group_name"], session[:user].id])
          @knowledge.group_id = group.id
        else
          # raise "Specified group is not found."
          @knowledge.group_id = nil
        end
      end
    end

    if session[:knowledge_figure]["figure_captions"].length == session[:knowledge_figure]["diagram_paths"].length
      session[:knowledge]["num_of_figure"] = session[:knowledge_figure]["diagram_paths"].length
    else
      raise "Unknown error."
    end
  end

  def destroy
    @knowledge = Knowledge.find(:first, :conditions => ["path=?", params[:path]], :user => session[:user])
    @knowledge.destroy
    redirect_to :action => 'list'
  end

  def temporary_save
    print "----- temporary_save -----\n"
    
    session[:knowledge]["title"] = params[:knowledge]["title"]
    session[:knowledge]["textbody"] = params[:knowledge]["textbody"]
    session[:knowledge]["knowledge_path"] = params[:knowledge]["knowledge_path"]
    session[:knowledge]["group_name"] = params[:knowledge]["group_name"]
    session[:knowledge]["default_layout"] = params[:knowledge]["default_layout"]
    session[:knowledge_figure]["figure_captions"] = Array.new
    session[:knowledge_figure]["figure_paths"] = Array.new
    if (params[:knowledge_figure] && params[:knowledge_figure].length > 0)
      print "num_of_figure = "
      pp session[:knowledge]["num_of_figure"]
      print "params = "
      pp params
      for i in 1 .. params[:knowledge_figure].length
        session[:knowledge_figure]["figure_captions"].push(params[:knowledge_figure][i.to_s]["figure_caption"])
        session[:knowledge_figure]["figure_paths"].push(params[:knowledge_figure][i.to_s]["figure_path"])
      end
    end
  end

  def create_from_new
    print "----- create_from_new -----\n"
    print "params = "
    pp params    
    if params[:commit] == "Create"
      create
    else
      # temporary_save
      redirect_to :action => "new"
    end
  end

  def create_from_edit
    print "----- create_from_edit -----\n"
    print "params = "
    pp params

    if (params[:commit] == "Save" || params[:commit] == "Save As")
      create
    else
      # temporary_save
      redirect_to :action => "edit", :id => params[:id]
    end
  end

  # Save images in this method, and call create method to make a knowledge document.
  def create_from_analysis
    print "----- create_from_analysis -----\n"
    print "session(knowledge) = "
    pp session[:knowledge]
    print "params = "
    pp params

    # temporary_save
    if params[:commit] == "Temporary Save"
      redirect_to :action => "new_from_analysis"
    elsif params[:commit] == "Create"
      ActiveRecord::Base::transaction do
        # save images
        if params[:knowledge_figure]
          print "params[knowledge_figure] = "
          pp params[:knowledge_figure]
          params[:knowledge_figure].each do |key, value|
            if key.to_i < 10
              auto_figure_path = "image00" + key.to_s
            elsif key.to_i < 100
              auto_figure_path = "image0" + key.to_s
            else
              auto_figure_path = "image" + key.to_s
            end
            id = value["diagram_id"]
            type = "diagram"
            name = value["name"]
            path = "knowledge/" + params[:node]["path"] + "/image/" + auto_figure_path #value["figure_path"]
            group = params[:knowledge]["group_name"]
            user = session[:user]
            
            # make realpath for figure.
            value["figure_path"] = "/usr/" + session[:user].login + "/knowledge/" + params[:node]["path"] + "/image/" + auto_figure_path #value["figure_path"]            

            # analysisの方が変わってるので、それに合わせてこの部分は変えなきゃいけないかも
            var = Variable.new
            diagram = get_temp_diagram(id)
            viz = diagram[:vizshot]
            pp viz
            ids = viz.get_variables.collect{|v|
              if Variable===v && ! v.id
                print "true!\n"
                from = v.file_and_variable_names[0]
                to, pa = auto_file_path("data")
                File.move(from, to)
                v.path = pa + Variable::DIR_VAR_DELIMITER + v.name
                v.save!
              else
                v = Variable===v ? v : Variable.find(v)
              end
              var.references_tmp << v
              v.id
            }

            img = Image.new
            img.vizshot = viz.to_yaml
            path = "/#{path}.png"
            from = diagrams_dir+"/"+diagram[:fname]
            img.name = name
            img.path = "/usr/#{user.login}#{path}"
            img.owner = user
            to = img.fname
            File.makedirs( File.dirname(to) )

            ## If none, make directory.
            # about groups
            unless params[:groups]
              raise "Check at least 1 group to visible!\n"
            else
              groups = params[:groups].values # Hash to Array
            end
            
            if groups[0] == 'everyone'
              other_mode = 4
              groups.shift
            else
              other_mode = 0
            end
            # make directories
            make_directories(img, user, groups, other_mode)            
            # save images
            if img.save
              messages = "successfully saved"
              print "successfully saved!\n"
              File.copy( from, to )
              diagram[:saved] = true
            else
              messages = "failed to save<br/>"
              print "failed to save!\n"
              messages += var.errors.full_messages.join("<br/>") if var.errors
            end
          end
        end
        create
      end
    else
      print "not Temporary or Create.\n  redirect!\n"
      redirect_to :action => "new_from_analysis"
    end
  end

  def create
    print "----- create -----\n"
    print "params = "
    pp params
    ## < knowledges table >
    if params[:commit]=="Save" # insert all original data include "@Knowledge.id"
      unless @knowledge = Knowledge.find(:first, :conditions => ["path=?", params[:original_path]], :user => session[:user])
        raise "Specified knowledge is not found or not yours."
      end
    else
      @knowledge = Knowledge.new
    end

    # about groups
    unless params[:groups]
      raise "Check at least 1 group to visible!\n"
    else
      groups = params[:groups].values # Hash to Array
    end

    if groups[0] == 'everyone'
      other_mode = 4
      groups.shift
    else
      other_mode = 0
    end
    @knowledge.other_mode = other_mode
    
    # insert title, textbody, default_layout
    @knowledge.attributes = {"title" => params[:knowledge]["title"]}
    @knowledge.attributes = {"textbody" => params[:knowledge]["textbody"]}
    @knowledge.default_layout = params[:knowledge]["default_layout"]
    
    # insert name, path, owner for knowledge.node
    @knowledge.name = params[:knowledge]["title"]
    if params[:original_path] && params[:commit] == "Save"
      @knowledge.path = params[:original_path]
    elsif params[:node]
      @knowledge.path = "/usr/"+ session[:user].login + "/knowledge/" + params[:node]["path"] + ".yml"
    else
      if params[:commit]=="Save"
        @knowledge.path = params[:original_path]
      else
        @knowledge.path = params[:new_path]
      end
    end
    @knowledge.owner = session[:user]
    @knowledge.node.set_rgroups(groups) if groups.length > 0

    # If none, make directory.
    File.makedirs( File.dirname(@knowledge.fname) ) or raise("failed to makedir")
    make_directories(@knowledge, session[:user], groups, other_mode)
        
    ## < knowledge_figures table >
    # if "Save", at first keep original knowledge_figures. (delete them later.)
    if params[:commit]=="Save"
      old_knowledge_figures = KnowledgeFigure.find(:all, :conditions => ["knowledge_id = ?", params[:id]])
    end

    knowledgefigures = Array.new
    if params[:knowledge_figure]
      # 今はうまくいっているが, 本来, key でソートすべき
      params[:knowledge_figure].each do |key, value|
        if value["figure_path"] != ""
          value["figure_path"] = value["figure_path"] + ".png"
          unless img = Image.find(:first, :conditions => ["path=?", value["figure_path"]], :user => session[:user])
            raise "Figure not found."
          end
          knowledgefigure = KnowledgeFigure.new(:caption => value["figure_caption"], :image_id => img.id)
          knowledgefigure.knowledge = @knowledge
          knowledgefigures.push(knowledgefigure)
        end
      end
    end

    @knowledge.knowledge_figures = knowledgefigures
        
    # save
    if @knowledge.save
      flash[:notice] = "A knowledge document is successfully saved."
      # if "Save", delete original knowledge_figures.      
      if params[:commit] == "Save"
        for old_kf in old_knowledge_figures
          old_kf.destroy
        end
      end
        redirect_to :action => 'list'
    else
      if params[:knowledge]["title"] == ""
        flash[:notice] = "Title is empty.Failed to save."
        redirect_to :action => "list"
      else
        flash[:notice] = "Failed to save."
        redirect_to :action => 'list'
      end
    end
  end

  def delete_knowledge_figures
    if params[:commit]=="Save"
      for ids in already_saved_figure_ids
        figure = KnowledgeFigure.find(ids)
        figure.destroy
      end
    else
      @knowledge.destroy
    end
  end

  def fig2analysis
    # vizshot_yaml = KeywordAttribute.find(:first, :conditions => ["variable_id = ? AND name = ?", params[:variable_id], 'vizshot'] )
    vizshot_yaml = Image.find_by_sql("SELECT * FROM images WHERE id=#{params[:image_id]}")[0].vizshot
    vizshot = YAML.load(vizshot_yaml)
    vizshot.find_variables
    
        analysis = Analysis.from_vizshot(vizshot)

    session[:analysis] = analysis
    session[:variables_list] = analysis.attributes["variables"]

    redirect_to :controller => "analysis", :action => "index"
  end

private
  def get_temp_diagram(id)
    diagrams = session[:diagrams]
    if diagrams
      return diagrams[id.to_i]
    else
      return nil
    end
  end

private
  def make_directories(obj, user, groups, other_mode)
    print "make_directories.\n"
    print "other_mode = "
    pp other_mode

    full_path = ""
    parent = nil
    obj.path.split(File::Separator)[0..-2].each{|dname|
      full_path = File.join(full_path, dname)
      dir = Directory.find(:first, :conditions=>["path=?",full_path], :user=>user)
      unless dir
        dir = Directory.new
        dir.name = dname
        dir.path = full_path
        dir.parent = parent.node
        dir.owner = user
        dir.other_mode = other_mode
        dir.node.set_rgroups(groups) if groups.length > 0
        if full_path == obj.file
          dir.downloadable = obj.downloadable?
          dir.plain_file = true
        end
        dir.save!
      end
      parent = dir
    }

  end


end
