#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
#
# アンケートの作成・編集
#
#@note
#「ステートについて」
# このコントローラでは、ステートを新規作成ステート・編集ステートと、
# もっともマクロな視点で使用している。
#
#「仕事の分離について」
# 作業中のデータはすべてセッション変数に入れて作業している。
# セッション上のデータ処理はすべてコントローラに行わせた。
# コントローラ内にアンケートクラスの都合が入り込んでいるようにも
# 見えるので、原理主義者にとっては居心地が悪いだろう。
# 緩い目で見れば、「セッション」というモデルと「アンケート」という
# モデルを、「コントローラ」が繋いでいようにも見える。
# 所詮、プログラムなんて妥協の産物。ここではそのあたりに
# バランス取りをしただけのこと。
# もしかすると、明日には、やはりダメだとか言いながら、セッション上の
# データ処理をアンケートクラスへ入れ込む作業をしているのかもしれない。
# そして、ほんの少しだけコントローラの行数が少なくなった事に満足して
# ほんの少しだけ処理速度が悪くなったことには目をつむるのだろう。
#

require 'al_template'
require 'al_form'
require 'al_persist'
require '../../enquete'


class AlController
  ##
  # constractor
  #
  def initialize()
    raise_state_error()
  end


  ##
  # default 新規作成モードで機動
  #
  def action_index()
    session.delete_all()
    set_state( "new_enquete" )
    session[:enquete_title] = {}
    session[:enquete_questions] = []

    action_edit_title()
  end


  ##
  # 編集モードで機動
  #
  def action_start_edit()
    session.delete_all()
    enq = Enquete.create_by_posted_id()
    raise "id error."  if ! enq

    set_state( "edit_enquete" )
    session[:enquete_title] = enq.enquete_title
    session[:enquete_questions] = enq.enquete_questions
    
    action_list()
  end


  ##
  # 複製モードで機動
  #@note
  # 実際には、そのモードがあるわけではなく、既存アンケートを読み込んだ上で、
  # 新規作成モードで動作させる。
  #
  def action_start_copy()
    action_start_edit()
    set_state( "new_enquete" )
  end


  ##
  # アンケート作成中のデフォルト画面
  #
  def action_list()
    @enquete = Enquete.new
    @enquete.enquete_title = session[:enquete_title]
    @enquete.enquete_questions = session[:enquete_questions]
    @form = @enquete.make_form()
    AlTemplate.run( "v_question_list.rhtml" )
  end


  ##
  # タイトルの編集
  #@note
  # 最初の表示とPOSTされたデータの処理を一括してこのメソッドで処理してみる。
  #
  def action_edit_title()
    @form = make_title_form()
    @form.action = Alone::make_uri( :action=>"edit_title" )

    # 最初のアクセスの時
    if ENV['REQUEST_METHOD'] == "GET"
      @form.values = session[:enquete_title]
      AlTemplate.run( 'v_edit_title.rhtml' )
      return
    end

    # バリデーションエラーの時
    if ! @form.validate()
      AlTemplate.run( 'v_edit_title.rhtml' )
      return
    end

    # 終了 => デフォルト画面へ
    session[:enquete_title].merge!( @form.values )
    action_list()
  end


  ##
  # 新規設問作成
  #
  def action_new()
    @form = make_question_form()
    @form.action = Alone::make_uri( :action=>'submit_page1' )
    session[:q_tmp] = {}
    session[:edit_number] = nil

    AlTemplate.run( 'v_edit_question_page1.rhtml' )
  end


  ##
  # 設問編集
  #
  def action_edit()
    number = AlForm.get_parameter( AlInteger.new( 'no', :required=>true ) )
    raise "no number specified."  if ! number

    # 入力済みのデータを取り出す
    session[:q_tmp] = session[:enquete_questions][ number ]
    raise "no question number specified."  if ! session[:q_tmp]
    session[:edit_number] = number

    # 入力フォーム表示
    @form = make_question_form()
    @form.action = Alone::make_uri( :action=>'submit_page1' )
    @form.values = session[:q_tmp]
    AlTemplate.run( 'v_edit_question_page1.rhtml' )
  end


  ##
  # 設問編集 - page1 設問入力完了
  #
  def action_submit_page1()
    @form = make_question_form()
    if ! @form.validate()
      AlTemplate.run( 'v_edit_question_page1.rhtml' )
      return
    end

    # 設問入力結果を保存
    session[:q_tmp].merge!( @form.values )

    # パターン０（説明文）ならこれで終了。
    if @form[:answer_pattern] == "p0"
      finish_edit()
      return
    end

    # 回答項目入力ページを表示
    @form = make_answer_form()
    @form.action = Alone::make_uri( :action=>'submit_page2' )
    @form.values = session[:q_tmp]
    AlTemplate.run( 'v_edit_question_page2.rhtml' )
  end


  ##
  # 設問編集 - page2 回答項目入力完了
  #
  def action_submit_page2()
    @form = make_answer_form()
    if ! @form.validate()
      AlTemplate.run( 'v_edit_question_page2.rhtml' )
      return
    end

    finish_edit()
  end


  ##
  # 設問削除
  #
  def action_delete()
    number = AlForm.get_parameter( AlInteger.new( 'no', :required=>true ) )
    raise "no number specified."  if ! number

    session[:enquete_questions].delete_at( number )
    reorder_question_number()

    Alone::redirect_to( Alone::make_uri( :action=>'list' ) )
  end


  ##
  # 位置の変更 上へ
  #
  def action_position_up()
    number = AlForm.get_parameter( AlInteger.new( 'no', :required=>true ) )
    raise "no number specified."  if ! number
    if number > 0
      tmp = session[:enquete_questions][number]
      session[:enquete_questions][number] = session[:enquete_questions][number-1]
      session[:enquete_questions][number-1] = tmp
    end
    reorder_question_number()
    action_list()
  end


  ##
  # 位置の変更 下へ
  #
  def action_position_down()
    number = AlForm.get_parameter( AlInteger.new( 'no', :required=>true ) )
    raise "no number specified."  if ! number
    if number < (session[:enquete_questions].count - 1)
      tmp = session[:enquete_questions][number]
      session[:enquete_questions][number] = session[:enquete_questions][number+1]
      session[:enquete_questions][number+1] = tmp
    end
    reorder_question_number()
    action_list()
  end


  ##
  # 作成完了／新規アンケート登録
  #
  def state_new_enquete_action_finish()
    enq = Enquete.new
    enq.enquete_title = session[:enquete_title]
    enq.enquete_questions = session[:enquete_questions]
    enq.create()

    session.delete_all()
    Alone::redirect_to( Alone::make_uri( :ctrl=>File.dirname(CTRL) ) )
  end


  ##
  # 作成完了／既存アンケート編集
  #
  def state_edit_enquete_action_finish()
    enq = Enquete.new
    enq.enquete_title = session[:enquete_title]
    enq.enquete_questions = session[:enquete_questions]
    enq.update()

    session.delete_all()
    Alone::redirect_to( Alone::make_uri( :ctrl=>File.dirname(CTRL) ) )
  end


  private
  ##
  # 一設問編集終了
  #
  def finish_edit()
    if session[:edit_number]
      session[:enquete_questions][ session[:edit_number] ] = session[:q_tmp].merge( @form.values )
    else
      session[:enquete_questions] << session[:q_tmp].merge( @form.values )
    end
    session.delete( :q_tmp )
    session.delete( :edit_number )
    reorder_question_number()

    Alone::redirect_to( Alone::make_uri( :action=>'list' ) )
  end


  ##
  # 質問番号をつけ直す。
  #
  def reorder_question_number()
    no = 1
    session[:enquete_questions].each do |q|
      if q[:answer_pattern] == "p0"
        q[:question_number] = nil
      else
        q[:question_number] = no
        no += 1
      end
    end
  end


  ##
  # タイトルフォーム作成
  #
  def make_title_form()
    return AlForm.new(
      AlText.new( 'title', :label=>'アンケートタイトル', :required=>true, :tag_attr=>{size: '50'} ),
      AlTextArea.new( 'title_note', :label=>"アンケートの説明", :rows=>5, :cols=>60 ),
      AlRadios.new( 'state', :label=>"状態",
        :options=>{ :making=>"作成中", :active=>"回答中", :closed=>"終了" },
        :value=>"making", :required=>true ),
      AlSubmit.new( 'submit', :value=>'決定' ),
    )
  end


  ##
  # 設問フォーム生成
  #
  def make_question_form()
    return AlForm.new(
      AlTextArea.new( 'question', :label=>'設問', :required=>true, :rows=>2, :cols=>60 ),
      AlRadios.new( 'answer_pattern', :label=>'回答パターン', :required=>true,
                    :options=>{ :p0=>"回答パターン０", :p1=>"回答パターン１", 
                      :p2=>"回答パターン２", :p3=>"回答パターン３", :p4=>"回答パターン４" } ),
    )
  end


  ##
  # 回答項目フォーム生成
  #
  def make_answer_form()
    case session[:q_tmp][:answer_pattern]
    when 'p1'
      return AlForm.new(
        AlInteger.new( 'rows', :label=>"入力欄 行数", :value=>1, :required=>true ),
        AlInteger.new( 'cols', :label=>"入力欄 幅", :value=>40, :required=>true ),
        AlRadios.new( 'required', :label=>"必須入力？", 
          :options=>{:true=>"必須入力とする", :false=>"空欄でもよい"}, :value=>"false" ),
        AlSubmit.new( 'submit', :value=>'決定', :tag_attr=>{:style=>'float: right;'} ),
      )
      
    when 'p2'
      return AlForm.new(
        AlTextArea.new( 'answer_text', :label=>"回答群", :filter=>'value.strip', 
            :required=>true, :rows=>8 ),
                        #:value=>"おいしい\r\nふつう\r\nまずい" ),
        AlRadios.new( 'arrange', :label=>"並び", :required=>true,
          :options=>{ :virtical=>"縦", :holizontal=>"横" }, :value=>"virtical" ),
        AlRadios.new( 'required', :label=>"必須入力？", 
          :options=>{:true=>"必須入力とする", :false=>"空欄でもよい"}, :value=>"false" ),
        AlSubmit.new( 'submit', :value=>'決定', :tag_attr=>{:style=>'float: right;'} ),
      )

    when 'p3'
      return AlForm.new(
        AlTextArea.new( 'answer_text', :label=>"回答群", :filter=>'value.strip', 
            :required=>true, :rows=>8 ),
                         #, :value=>"天然塩\n有機野菜\nあいがも米" ),
        AlRadios.new( 'arrange', :label=>"並び", :required=>true,
          :options=>{ :virtical=>"縦", :holizontal=>"横" }, :value=>"virtical" ),
        AlInteger.new( 'max_select', :label=>"最大選択数" ),
        AlInteger.new( 'min_select', :label=>"最少選択数" ),
        AlRadios.new( 'required', :label=>"必須入力？", 
          :options=>{:true=>"必須入力とする", :false=>"空欄でもよい"}, :value=>"false" ),
        AlSubmit.new( 'submit', :value=>'決定', :tag_attr=>{:style=>'float: right;'} ),
      )

    when 'p4'
      return AlForm.new(
        AlTextArea.new( 'answer_text', :label=>"回答群", :filter=>'value.strip', :required=>true, :rows=>8 ),
        AlRadios.new( 'answer_type', :label=>"回答入力の種類", :required=>true,
          :options=>{ :text=>"文字", :int=>"数字(整数)", :float=>"数字(小数)" }, :value=>"text" ),
        AlInteger.new( 'box_size', :label=>"入力欄サイズ", :value=>10, :required=>true ),
        AlRadios.new( 'arrange', :label=>"並び", :required=>true,
          :options=>{ :virtical=>"縦", :holizontal=>"横" }, :value=>"virtical" ),
        AlRadios.new( 'required', :label=>"必須入力？", 
          :options=>{:true=>"必須入力とする", :false=>"空欄でもよい"}, :value=>"false" ),
        AlSubmit.new( 'submit', :value=>'決定', :tag_attr=>{:style=>'float: right;'} ),
      )
    end
  end    

end
