
#
# EDINET のインスタンスデータを読み込んで、csv に変換する。
#  2008-01-10 katoy
#  2008-04-20 katoy
#  2008-05-03 katoy    Version = "0.1.2 (2008-05-03)"
#  2009-05-03 katoy    Version = "0.1.3 (2009-05-03)"
#                      ファイル出力を追加
#  2009-05-16 katoy    Version = "0.1.4 (2009-05-16)"
#                      DocumentInfo 以外の Context の値がすべて nil や "" の行は出力しない。
#                      EDINET の zip ファイル指定を可能にする。
#  2009-05-17 katoy    Version = "0.1.5 (2009-05-17)"
#                      複数インスタンスを含む zip にも対応。
#                      複数インスタンスをコマンドラインに指定可能。
#                      複数インスタンスを処理する場合は 企業名も出力する。

# How to run:
#   $ ruby edinet2csv.rb ../sample/X99003-000/jpfr-q2r-X99003-000-2008-09-30-01-2008-11-26.xbrl > 1.csv
#    出力結果の csv を NeoOffice などで読み込む。
#　　$ ruby edinet2csv.rb -help
#    簡易ヘルプを表示する。
#　　$ ruby edinet2csv.rb --version
#    version を表示する。
#   備考： このプログラムは jruby でも動作する。

require 'pp'
require 'optparse'
require 'edinetzip'
require 'xbrl'
require 'edinetcode'

$KCODE="utf8"

Version = "0.1.5 (2009-05-17)"  # opt.version
INDENT = "    "  # space * 4

def print_tree(fileArray, nest = 0, indent = INDENT)
  fileArray.each {|e|
    if e.class.name == "Array"
      printTree(e, nest + 1)
    else
      puts "#{indent * nest}#{e}"
    end
  }
end

class String                    # from [ruby-list:41779], for YAML bug
  def is_binary_data?
    return true if self.include?(0)
    check = self[0, 512]
    check.size < 10 * check.count("\x00-\x07\x0b\x0e-\x1a\x1c-\x1f")
  end
end

# for DEBUG
def show_info(xbrl)
  puts "==== items ===="
  puts xbrl.items.to_yaml

  puts "==== elements ===="
  puts xbrl.elements.to_yaml

  puts "==== labels ===="
  puts xbrl.labels.to_yaml

  puts "==== files ===="
  print_tree xbrl.files

  puts "==== ignore files ===="
  print_tree xbrl.ignoreFiles
end

# csv 形式で、インスタンスデータを [科目の出現順 x コンテキストの出現順] で出力する。
def my_show_table(xbrl, lang="ja", out=STDOUT)
  contexts = xbrl.contexts
  table = xbrl.get_instance_table(lang)

  title = ["", ""]
  title << contexts.keys.to_a
  out.puts title.join(",")

  title = ["", ""]
  title << contexts.values.to_a
  out.puts title.join(",")

  table.each {|k, v|
    has_value = false
    vStr = [v[:label]]
    contexts.each {|ck, cv|
      val = v[ck]
      val = "" if val == nil
      has_value = true if ck != :DocumentInfo and val != ''
      vStr << val
    }
    out.puts "#{k},#{vStr.join(',')}" if has_value
  }
end

# csv 形式で、諸表を出力する。
def my_show_sheet(xbrl, lang="ja", out=STDOUT)
  contexts = xbrl.contexts
  table = xbrl.get_instance_table(lang)
  sheets = xbrl.get_edinetsheets(lang)

  sheets.each {|sheet|

    title = [sheet[:name], ""]
    title << contexts.keys.to_a
    out.puts title.join(",")

    title = ["", ""]
    title << contexts.values.to_a
    out.puts title.join(",")


    sheet[:labels].each {|row|
      id = "#{row[12]}:#{row[13]}" # prefix:name を合成する
      v = table[id]
      next if v == nil

      vStr =  [v[:label]]
      contexts.each {|ck, cv|
        val = v[ck]
        val = "" if val == nil
        vStr << val
      }

      depth = row[22].to_i - 1 # row[22]: depth
      depth = 0 if depth < 0
      vStr[0] = INDENT * depth + vStr[0]
      out.puts "#{id}, #{vStr.join(',')}"
    }

  }
end

#--------- 呼び出し例 -----------
if __FILE__ == $0
  #file_path = "../../XBRL-CONF-CR3-2007-03-05/Common/instance/397-00-ConsistentInstance-valid.xbrl"
  #file_path = "../../sample2009-03-09/X99001-000/jpfr-asr-X99001-000-2009-03-31-01-2009-06-27.xbrl"
  #file_path = "../../sample2009-03-09/X99002-000/jpfr-q1r-X99002-000-2009-06-30-01-2009-08-08.xbrl"
  #file_path = "../../sample2009-03-09/X99003-000/jpfr-q2r-X99003-000-2009-09-30-01-2009-11-26.xbrl"
  #file_path = "../../sample2009-03-09/X99004-000/jpfr-q3r-X99004-000-2009-12-31-01-2010-02-10.xbrl"
  #file_path = "../../sample2009-03-09/X99005-000/jpfr-asr-X99005-000-2009-03-31-01-2009-06-27"
  #file_path = "../../sample2009-03-09/X99005-001/jpfr-asr-X99005-001-2009-03-31-01-2009-06-27.xbrl"
  #file_path = "../../sample2009-03-09/X99006-000/jpfr-ssr-X99006-000-2009-09-30-02-2009-12-26.xbrl"
  #file_path = "../../sample2009-edinet/XBRL_20090510_073314.zip"
  #file_path = "../../sample2009-edinet/XBRL_20090517_155420.zip"
  #ARGV << file_path

  sheet_p = false
  lang_p="ja"
  out_path = ''

  ARGV.options {|opt|
    opt.banner = "\nUsage: #{$0} [options] xbrl"
    opt.on('-s', '--sheet', "output sheet form.") {|v| sheet_p = true }
    opt.on('-i', '--item', "output all instance items. (default)") {|v| sheet_p = false }
    opt.on('--lang=[en|ja]', "lang for label-name. (default=ja)") {|v| lang_p = v }
    opt.on('--out=[file_name]', "output (default=STDOUT)") {|v| out_path = v }
    def opt.error(msg = nil)
      $stderr.puts msg if msg
      $stderr.puts help()
      exit 1
    end

    begin
      opt.parse!
    rescue OptionParser::ParseError => err
      opt.error err.message
    end
  }

  ARGV.options.error if ARGV.size == 0

  instance_paths = EdinetZip::get_instance_files(ARGV)

  if instance_paths.size == 0
    exit(-1)
  end

  edinet_code = EdinetCode.new if instance_paths.size > 0

  instance_paths.each do |instance|

     if instance_paths.size > 0
      c = edinet_code.info[EdinetCode::get_code_from_path(instance)]
      $stderr.puts "==== #{c[:NAME]} ====" if c != nil
      puts "\"#{c[:NAME]}\"" if c != nil
     end

      xbrl = Xbrl.new
    xbrl.parse_instance(instance)
    begin
      f = (out_path == '')? STDOUT : File.open(out_path, "w")
      sheet_p ? my_show_sheet(xbrl, lang_p, f): my_show_table(xbrl, lang_p, f)
    rescue => ex
      p ex
    ensure
      f.close if f != STDOUT and f != nil
    end
  end
end

#--- End of File
