#!/usr/bin/env ruby
Version = '0.00'
Myname = File.basename($0)

require 'optparse'
require 'colorize'

Help=
<<'DOC'
= cvged - convert gedcom file making linked notes inline

= Synopsis
	cvged old.ged > new.ged

= Description
cvged replaces linked notes in a GEDCOM file with inline notes.
At the same time it inserts proper indentation. By default the
indentation is two spaces per level. This can be chaged by setting
INDENT to another value.

= Author
[Wybo Dekker](wybodekker@me.com)

= Copyright
Released under the [GNU General Public License](www.gnu.org/copyleft/gpl.html)
DOC

INDENT = ' '

def warn(*m) mess :magenta,*m if $o.verbose; end
def Warn(*m) mess :magenta,*m; end
def die(*m) mess :red,*m; exit 1; end
# print colored string(s), 1 line per argument
def mess(color,*m)
   name = Myname + ': '
   m.each do |v|
      STDERR.puts "#{name}#{v}".__send__(color)
      name.gsub!(/./,' ')
   end
end

def help
  nv="-#{Myname}-#{Version.sub(/\./,'\\.')} press h for help, q to quit"
  IO.popen("less -P'#{nv}'",'w') do |pipe| pipe.puts Help end
end

OptionParser.new(
   banner = <<~EOD,
	convert gedcom file making linked notes inline
	EOD
   width = 15,
   indent = ''
) do |opts|
   opts.separator ""

   opts.on('-h','print this help and exit') do
      puts opts.to_a.delete_if { |x| x =~ /—$/}
      exit
   end
   
   opts.on('-H','--Help',
      'show full documentation (use less!) and exit'
   ) do
      help
      exit
   end
   
   opts.on('-V','--version','print version and exit') do
      puts Version
      exit
   end
   
   opts.on('-I','—') do
      system("instscript #{Myname}") or
         die 'the -I option is for developers only'
      exit
   end
   opts.parse!
end


# print a line indented properly
def pr(s)
  s.chomp!
  if s[/\s*(\d)\s*(.*)/]
    puts INDENT*$1.to_i + $1 + ' ' + $2
  else 
    # lines not starting with a \s*\d are simply copied:
    puts s
  end
end

notes = {}
notekey = nil

ARGV.size == 1 or raise "Need 1 input file"
ged = open(ARGV[0]) or raise "Couldn't open: #{$!}"

# scan the file for non-internal notes and save those in a hash:
while line = ged.gets do
  case line
  when /^\s*0\s+@N(.*)@/
    notekey = $1
    STDERR.print notekey + ' '
    notes[notekey] = []
  when /^\s*\d\s+(CON.*)/
    notes[notekey].push($1) if notekey
  else
    notekey = nil
  end
end
STDERR.puts ''

# scan the file again, replacing linked notes woth inline notes:
ged.rewind
while line = ged.gets do
  case line
  when /^\s*0\s+@N/
    # linked notes are supposed to have been defined at the end!!:
    pr('0 TRLR')
    exit 0
  when /^\s*(\d)\s+NOTE\s+@N(.*)@/
    depth,notekey = $1,$2
    notes[notekey] or raise "Unknown note #{notekey} at line #{$.}" 
    pr("#{depth} NOTE")
    notes[notekey].each do |n| pr("#{depth.to_i+1} #{n}") end
  else
    pr(line)
  end
end
