require 'rubygems'
require 'rjb'

module Poi
  class ExcelPoi
    include Comm::Const::Print
    #REGEX_SIMPLE_INT = Regexp.new('^\d+$')
    #数値変換のために、"0"だけ以外の0から始まる文字列を外しています
    #REGEX_FLOAT = Regexp.new('(?!^0.+$)^[-+]?\d+\.\d+$')
    REGEX_FLOAT = Regexp.new('^-?(0|[1-9]\d*)\.\d+$')
    REGEX_INT = Regexp.new('(?!^0.+$)^[-+]?\d+$')
    REGEX_DATE_STR = Regexp.new('^[12]\d{3}-[01]\d-[0-3]\d$')
    INT_MAX = 2147483647
    
    #dispname取得のキー
    REGEX_DISP_NAME_KEY = Regexp.new('(_code|_id)$')
    #見栄えのための上左余白（今更変更するとたぶん怒られる）
    COL_INIT_VAL = 1
    ROW_INIT_VAL = 1
    
    def initialize(opts={})
      #Rjb::load(classpath = File.expand_path(File.join(File.dirname(__FILE__), 'poi.jar')), jvmargs=['-Xms256m', '-Xmx512m'])
      @file_class = Rjb::import('java.io.FileOutputStream')
      @workbook_class = Rjb::import('org.apache.poi.hssf.usermodel.HSSFWorkbook')
      @cell_style_class = Rjb::import('org.apache.poi.hssf.usermodel.HSSFCellStyle')
      #@data_format_class = Rjb::import('org.apache.poi.hssf.usermodel.HSSFDataFormat')
      
      @tmp_path =  opts[:tmp_path] ? opts[:tmp_path] : Dir.tmpdir+'/'+rand(100000).to_s+Time.now.to_i.to_s
      @sheet_name = opts[:sheet_name] ? opts[:sheet_name] : 'sheet1'
    end
    
    def output(hash_array, col_info, opts={})
      book = @workbook_class.new
      sheet = book.createSheet(@sheet_name)
      sheet.setDefaultColumnWidth(20)
      #最初の空列は2文字分開ける
      sheet.setColumnWidth(0, 512)
      row_cnt,col_cnt=ROW_INIT_VAL,COL_INIT_VAL
      col_length=col_info.length
      
      #header
      row = sheet.createRow(row_cnt)
      head_style = create_style(book, true)
      col_length.times do |i|
        cinfo = col_info[i.to_s]
        tmp_value = cinfo['v']
        if cinfo['t'] == 'list'
          col_cnt = set_value(row, col_cnt, tmp_value+'(ID)', head_style)
        end
        col_cnt = set_value(row, col_cnt, tmp_value, head_style)
      end
      row_cnt += 1
      col_cnt = COL_INIT_VAL
      
      #data
      create_style(book)
      regex_simple_int = Regexp.new('^\d+$')
      for hash in hash_array
        row = sheet.createRow(row_cnt)
        col_length.times do |i|
          cinfo = col_info[i.to_s]
          key = cinfo['f']
          value = hash[key]
          if value.blank? && key =~ regex_simple_int
            value = hash[key.to_i]
          end
          col_cnt = set_value(row, col_cnt, value)
          if cinfo['t'] == 'list'
            key = key.gsub(REGEX_DISP_NAME_KEY,'_dn')
            col_cnt = set_value(row, col_cnt, value)
          end
        end
        col_cnt = COL_INIT_VAL
        row_cnt += 1
      end
      
      out = @file_class.new(@tmp_path)
      book.write(out)
      out.close
      return {:success=>true,
              :file_name=>get_file_name,
              :tmp_file_name=>@tmp_path,
              :file_type=>get_file_type}
    end
    
    def create_style(book, is_header=false)
      style = book.createCellStyle
      style.setBorderRight(@cell_style_class.BORDER_THIN)
      style.setBorderLeft(@cell_style_class.BORDER_THIN)
      
      if is_header
        style.setBorderTop(@cell_style_class.BORDER_THIN)
        style.setBorderBottom(@cell_style_class.BORDER_DOUBLE)
        style.setAlignment(@cell_style_class.ALIGN_CENTER)
      else
        style.setBorderBottom(@cell_style_class.BORDER_THIN)
        @default_style ||= style
      end
      return style
    end
    
    def set_value(row, col_cnt, value, style=@default_style)
      if value == nil
        value = ''
      elsif value.is_a?(String)
        if value =~ REGEX_INT
          tmp_val = value.to_i
          if tmp_val < INT_MAX
            value = tmp_val 
          end
        elsif value =~ REGEX_FLOAT
          value = value.to_f
#        elsif value =~ REGEX_DATE_STR
#          value = Date.parse(value)
        end
      elsif value.instance_of?(Date)
        value = value.strftime("%Y/%m/%d")
      elsif value.instance_of?(Time)
        value = value.strftime("%Y/%m/%d %H:%M:%S")
      elsif value.is_a?(BigDecimal)
        value = value.to_f
      end
      
      cell = row.createCell(col_cnt)
      begin
        cell.setCellValue(value)
      rescue=> e
        Rails.logger.info("RJB POI FORMAT ERROR - VAL:"+value.inspect+' CLASS:'+value.class.inspect)
        Rails.logger.info(e.message + "\n" + e.backtrace.join("\n"))
        cell.setCellValue(value.to_s)
      end
      cell.setCellStyle(style)
      return col_cnt+1
    end
    
    def get_file_name(opts={})
      unless opts[:basename]
        opts[:basename] = @mcls ? @mcls.name.underscore : ''
      end
      opts[:uniqstr] ||= Time.now.strftime("%y%m%d-%H%M")
      opts[:extension] ||= '.xls'
      return opts[:basename]+'-'+opts[:uniqstr]+opts[:extension]
    end
    
    def get_file_type
      return FILE_TYPE_INFO[0][:ctype]
    end
  end
end