#
#= リクエストパラメーター処理モジュール
# Authors:: Sumiyo Yamamoto
# Copyright:: Copyright (C) OrbusNeich Medical K.K.  2010.
#--
# date        name                   note
# 2010.2.19   Sumiyo Yamamoto        新規作成
#-------------------------------------------------------------------------------
#++
module Comm
  module Module
    #= リクエストパラメーター処理モジュール
    # リクエストパラメーター処理に使えるメソッド群を備える。
    #------------------------------------------------------------------------#++
    module Params

      #== ページ設定・検索条件編集
      #
      # 戻り値:: find引数形式の検索条件
      #-----------------------------------------------------------------#++
      def get_options
        get_paginate_options.merge(get_search_options.merge(get_select_options))
      end
      
      #== カラムの指定オプション
      def get_select_options
        results = {}
        unless params[:cols].blank?
          results[:select] = params[:cols]
        end
        return results
      end
      #== ページ設定編集
      # パラメーターからページ設定(limit, sort関連)を取り出し、findの引数形式に編集する。
      #
      # 戻り値:: find引数形式の検索条件
      #-----------------------------------------------------------------#++
      def get_paginate_options
        results = {}
        pagination_state = {}
        
        if params[:show_all].blank?
          #-- 開始位置    #++
          tmp = (params[:start] || 0)
          results[:offset] = tmp.to_i
          
          #-- 終了位置    #++
          tmp = (params[:limit] || 9223372036854775807)
          results[:limit] = tmp.to_i
        end
        
        # ソート
        col_name = get_sql_column_name(params[:sort])
        sort_field = add_table_name(col_name, @table_name)
        unless sort_field.blank?
          sort_direction = (params[:dir] || 'ASC').to_s.upcase
          results[:order] = "#{sort_field} #{sort_direction}"
        end
        return results
      end

      #== 検索条件編集メイン
      # パラメーターから検索条件(WHERE)を取り出し、findの引数形式に編集する。
      #
      # 戻り値:: find引数形式の検索条件
      #-----------------------------------------------------------------#++
      def get_search_options
        results = {}
        filter_condition = ''
        query_hash=Hash.new
        
        # Filterオプション編集
        unless params[:filter].blank?
          tmp_condition = build_filter_options(params[:filter], @table_name, query_hash, "AND")
          unless tmp_condition.empty?
            filter_condition = '(' + tmp_condition + ')'
          end
        end
        # Searchオプション編集
        unless params[:search].blank?
          tmp_condition = build_filter_options(params[:search],@table_name, query_hash, "OR")
          unless (tmp_condition.empty?)
            unless filter_condition.empty?
              filter_condition = filter_condition + ' AND '
            end
            filter_condition = filter_condition + '(' + tmp_condition + ')'
          end
        end
        
        # find 引数形式編集
        unless filter_condition.empty?
          results.merge!({:conditions => [filter_condition , query_hash]})
        end
        return results
      end

      #== 指定項目のオプション取得
      # Search、又はFilterオプションの中から、指定項目のオプションのみを取得する。
      #_filter_hash_:: Search、又はFilterオプション
      #_col_name_:: 項目名
      #
      # 戻り値:: 指定項目のパラメーター（無かった場合はnil）
      #-----------------------------------------------------------------#++
      def get_target_options(filter_hash = {}, col_name = nil)
        result = nil
        unless filter_hash.blank?
          filter_hash.each do |columns, fvals|
            gf_field = get_sql_column_name(fvals[:field])
            if gf_field == col_name
              result = fvals
              break
            end
          end
        end
        
        return result
      end

      #== 指定項目のオプション削除
      # Search、又はFilterオプションの中から、指定項目のオプションのみを削除する。
      #_filter_hash_:: Search、又はFilterオプション
      #_col_name_:: 項目名
      #
      # 戻り値:: 指定項目のパラメーター（無かった場合はnil）
      #-----------------------------------------------------------------#++
      def delete_target_options(filter_hash = {}, col_name = nil)
        result = nil
        
        unless filter_hash.blank?
          # 指定項目の検索
          target_columns = nil
          filter_hash.each do |columns, fvals|
            gf_field = get_sql_column_name(fvals[:field])
            if gf_field == col_name
              target_columns = columns
              result = fvals
              break
            end
          end
          
          # 削除
          if target_columns
            filter_hash.delete(target_columns)
          end
        end
        
        return result
      end

    protected
      #== SQL検索条件文字列編集
      # Search、又はFilterオプションから、SQL検索条件文字列を編集する。
      #_filter_hash_:: Search、又はFilterオプション
      #_table_name_:: 検索対象のメインテーブル名
      #_query_hash_:: 文字列検索の文字列値集合（戻り値）
      #_condition_:: AND/OR条件
      #
      # 戻り値:: find引数形式の検索条件文字列
      #-----------------------------------------------------------------#++
      def build_filter_options(filter_hash = {}, table_name = nil, query_hash = {}, condition = nil)
        result = ''
        
        # フィルタ設定がない場合は空文字を返す。
        if filter_hash.nil?
          return result
        end
        
        # 設定値がないものは除去する。
        filter_hash = filter_hash.delete_if {|key, value| value.blank? }
        
        filter_hash.each do |columns, fvals|
          fstring = ''
          
          # 検索条件のカラム名編集(gf_field)
          col_name = get_sql_column_name(fvals[:field])
          gf_field = add_table_name(col_name, table_name)
          
          # 検索タイプ編集(gf_type)
          #   numeric, string, boolean, list, date
          gf_type = fvals[:data][:type].downcase
          
          # 検索値(gf_value)
          gf_value = fvals[:data][:value]
          
          # 比較検索条件編集(gf_comparison)
          #   >, <, =, !=
          gf_comparison = get_sql_comparison(fvals[:data][:comparison], gf_type)
          
          case gf_type
            #-- 数値
            #++
          when 'numeric'
            unless gf_comparison.empty?
              fstring = gf_field + ' ' + gf_comparison + ' ' + gf_value.to_i.to_s
            end
          #-- 文字列    #++
          when 'string'
            i = query_hash.length
            condition_array = Array.new
            gf_value.split(/[\s　]+/).each do |query|
              query_hash["filter#{i}".to_sym] = "%#{query}%"
              condition_array << gf_field + ' LIKE ' + ":filter#{i}"
            end
            fstring = '(' + condition_array.join(' OR ') + ')'
          #-- boolean    #++
          when 'boolean'
            gf_value = gf_value.downcase
            if (gf_value == 'true') || (gf_value == 'false')
              fstring = gf_field + ' = ' + gf_value
            end
          #-- リスト    #++
          when 'list'
            fstring = build_filter_options_list(gf_field, gf_value)
          #-- 日付    #++
          when 'date'
            unless gf_comparison.empty?
              fstring = gf_field + ' ' + gf_comparison + ' \'' + gf_value + '\''
            end
          end
          
          unless fstring.empty?
            unless result.empty?
              result += ' '+ condition + ' '
            end
            result += fstring
          end
        end
        
        return result
      end
      
      #== SQL検索条件文字列編集(リスト)
      # Search、又はFilterオプションから、SQL検索条件文字列を編集する。
      #_key_:: 検索カラム名
      #_list_val_:: 検索値
      #
      # 戻り値:: find引数形式の検索条件文字列
      #-----------------------------------------------------------------#++
      def build_filter_options_list(key = nil, list_val = nil)
        result = ''
        
        if (list_val.blank?) || (key.blank?)
          return result
        end
        
        #key = key + ' = '
        cnt = 0
        #list_val.split(',').each do |val|
        list_val.split(/','|\s+/).each do |val|
          unless cnt < 1
            result += ' OR '
          end
          if val == "-1"
            result += key + ' is NULL OR ' + key + ' < 0 '
          else
            result += key + ' = "' + val + '"'
          end
          cnt += 1
        end
        
        unless cnt <= 1
          result = '(' + result + ')'
        end
        
        return result
      end

      #== 比較条件HTML形式→SQL形式変換
      #-----------------------------------------------------------------#++
      def get_sql_comparison(comp_str = nil, gf_type = nil)
        result = ''
        case comp_str
        when 'gt'
          #if gf_type == 'date'
            result = '>='
          #else
          #  result = '>'
          #end
        when 'lt'
          #if gf_type == 'date'
            result = '<='
          #else
          #  result = '<'
          #end
        when 'eq'
          result = '='
        when 'ne'
          result = '!='
        end
        return result
      end

      #== カラム名HTML形式→SQL形式変換
      #   ex1. product[product_name]→product_name
      #   ex2. product[product_categories.type]→product_categories.type
      #-----------------------------------------------------------------#++
      def get_sql_column_name(col_name = nil)
        result = ''
        
        if col_name.blank?
          return result
        end
        
        result = col_name.downcase.sub(/(\A[^\[]*)\[([^\]]*)\]/,'\2')
        
        return result
      end

      #== カラム名にテーブル名を追加する
      #-----------------------------------------------------------------#++
      def add_table_name(col_name = nil, table_name = nil)
        result = ''
        
        if col_name.blank?
          return result
        end
        
        re1 = Regexp.new(Regexp.quote("."))
        # カラム名のみの場合(ex1)
        if (re1 =~ col_name).nil?
          result = "#{table_name}.#{col_name}"
        # テーブル名.カラム名の場合(ex2)
        else
          result = col_name.to_s.sub(/^\./, '')
        end
        
        return result
      end
    end
  end
end
