#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'sqlite3'
require 'cgi'
require 'kconv'
require 'tmpdir'
require 'json'

db = "../viewerdb/db/viewer_prc.sq3"
c = CGI.new(:accept_charset=>'utf-8')

mydir=File.dirname($0)
@mapdb = SQLite3::Database.new(db)
@mapdb.results_as_hash = true
@tmpdir = ENV["TMPDIR"] || "tmp"
@resizepx = 1280
@imgprocscript = "%s/imgpublisher.sh" % mydir
updater = nil
reqpars = {
  'ename'	=> /^[-a-z_.0-9]+$/,
  'name'	=> /./,
  'addr'	=> /.../,
  'latlon'	=> /^\d+\.\d+,\s*\d+\.\d+$/,
  'maptype'	=> /^[-a-z_.0-9]+$/,
  'description'	=> /...../
}
def content(file)
  open(file){|f| f.read.toutf8}
end
def cat(file)
  print(content(file))
end
def db2options(selection)
  opts = ""
  @mapdb.execute("SELECT DISTINCT #{selection}") do |row|
    opts += sprintf("<option value=\"%s\">%s</option>\n",
                    CGI.escapeHTML(row[0].toutf8.gsub('"', "")),
                    CGI.escapeHTML(row[1]||row[0]||""))
  end
  opts
end
def process_data(cgi)
  test(?w, @tmpdir) or abort "Cannot output files to #{@tmpdir}"
  basename = cgi.params["ename"][0].strip.gsub(/\s/, "")
  filenames = []
  dir = Dir.mktmpdir(nil, File.expand_path(@tmpdir))
  cgi.params["photo"].each do |img|
    ext = File.extname(img.original_filename).downcase.sub(/jpeg$/, "jpg")
    fn = sprintf("%s-%d%s", basename, 1 + filenames.length, ext)
    open(dir+"/"+fn, "w"){|f| f.write(img.read)}
    filenames << fn
  end
  Dir.chdir(dir) do
    # system "ls -lF"
    pid = fork {
      exec(@imgprocscript, "-l", cgi["latlon"])
    }
    $stdout.close
  end
end
def prepareJSdata()
  globalvar = "entInit_mapitems"
  data = {}
  r = @mapdb.execute(<<-EOF)
	SELECT	ename, name, addr, lat, lon
	FROM	mapitem NATURAL JOIN maptype
	EOF
  r.each do |row|
    ename = row['ename']
    data[ename] ||= {}
    ["name", "addr", "lat", "lon"].each do |i|
      data[ename][i] = row[i]
      data[ename]["latlon"] = row['lat'].to_s+", "+row['lon'].to_s
    end
  end
  printf(<<-EOF, globalvar, JSON.pretty_generate(data))
	<script type="text/javascript" charset="utf-8">
	<!--
	 var %s = %s;
	// -->
	</script>
	EOF
end
def updatedb(params)
  ename, name, addr, latlon, maptype, description =
    params['ename'][0], params['name'][0], params['addr'][0],
  params['latlon'][0],
  params['maptype'][0], params['description'][0]
  lat, lon = latlon.scan(/(\d+.\d+),\s*(\d+.\d+)/)[0]
  # p ename, description
  puts "<pre>"
  printf("%s|%s|%s|%s|%s|%s", *[ename, name, addr, lat, lon, description])
  @mapdb.transaction do |d|
    d.execute(<<-EOF, ename, name, addr, lat.to_f, lon.to_f)
	REPLACE INTO mapitem(ename, name, addr, lat, lon)
	VALUES  (?, ?, ?, ?, ?);
	EOF
    d.execute(<<-EOF, ename, 'description', description)
	REPLACE INTO attribute(ename, attr, value)
	VALUES  (?, ?, ?);
	EOF
  puts "</pre>"
  end
end
def returnJSON(entity)
  data = {}
  entity.gsub!(/[^-0-9a-z._]/, "")
  print "Content-type: text/plain; charset=UTF-8\n\n"
  r = @mapdb.execute(<<-EOF, entity)[0]
	SELECT	i.ename, name, addr, lat, lon,
		printf("%s, %s", lat, lon) as latlon,
		attr, value as description
	FROM	mapitem i LEFT JOIN attribute a
	ON	i.ename=a.ename AND a.attr='description'
	WHERE	i.ename=?
	EOF
  if r
    STDERR.puts JSON.generate(r)
    print JSON.generate(r)
  else
    puts "[]"
  end
end

# ARGV[0]=="get/ENTITY" returns its attributes in JSON format
if ARGV[0] && %r,^get/([-0-9a-z._]+)$,i =~ ARGV[0]
  returnJSON($1)
  exit 0
end

print "Content-type: text/html; charset=utf-8\n\n"
ef = content("ent-form.html")
if c.params['submitting'][0]
  invalid = false			# Validating parameters
  reqpars.each do |par, ptn|
    classholder = "__%sIV__" % par.upcase
    if !c.params[par][0] || ptn !~ c.params[par][0]
      invalid = true
      ef.gsub!(classholder, ' class="e"')
    else
      ef.gsub!(classholder, '')
    end
  end
  if invalid
    ef.gsub!("__INVALMSG__", "赤地の部分の記入が不十分です。")
  else
    ef.gsub!("__INVALMSG__", "")
    description = c['description'].chomp+"\n"
    if c.params["photo"][0] != ""	# XXX: is it OK?
      i, o = IO.pipe
      pid = fork do
        # i.close
        $stdout.reopen(o)		# We should substitute stdio here
        $stdin.close			# to avoid blocking to web-client
        process_data(c)
      end
      o.close
      while line=i.gets			# Reading repetition of {{IMGURL}}
        if %r,{{.*\/(\S+.jpg)}}, =~ line
          if !description.index($1)	# Already desc. contains no filename
            # THINK! Adding at the BOTTOM is nice or not!?
            description += line
          end
        end
      end
    end
    # Then update DB!
    updater = lambda{updatedb(c.params.merge({'description'=>[description]}))}
  end
else
  ef.gsub!(/__\w+IV__/, "")
end

for v in reqpars.keys
  ef.gsub!("__"+v.upcase+"__", CGI.escapeHTML(c.params[v][0]||""))
end
cat("ent-header.html")
print ef.gsub(/__{(.*)}__/) {db2options($1)}
prepareJSdata
updater and updater.call
cat("footer.html")
