#!/usr/bin/env python
# coding: UTF-8

import sqlite3
import math
from pprint import pprint

def queue_render(db,filename,forced_max_zoom=None):

  conn = sqlite3.connect(db)
  conn.text_factory = str
  cur = conn.cursor()
        
  cur.execute("select minlat,minlon,maxlat,maxlon from tracks where filename=?" , (filename,))
  minlat,minlon,maxlat,maxlon=cur.fetchone()
  queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom)

def deg2num(lat_deg, lon_deg, zoom):
  lat_rad = math.radians(lat_deg)
  n = 2.0 ** zoom
  xtile = int((lon_deg + 180.0) / 360.0 * n)
  ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
  return (xtile, ytile)
            
def queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom=None):

  conn = sqlite3.connect(db)
  
  # определяем примерный стартовый зум

  minzoom=8

  if forced_max_zoom:
    maxzoom=forced_max_zoom
  else:
    maxzoom=minzoom
    while True:
      minx,miny=deg2num(minlat,minlon,maxzoom)
      maxx,maxy=deg2num(maxlat,maxlon,maxzoom)
      
      print(maxzoom,':',minx,'-',maxx,'/',miny,'-',maxy)
      if (maxx-minx>16) or (maxy-miny>12) or (maxzoom==16):
        break
      else:
        maxzoom=maxzoom+1   
  
  if maxzoom<minzoom:
    minzoom=maxzoom
  
  ins = conn.cursor()
  print(minlat,minlon,maxlat,maxlon,minzoom,maxzoom)
  ins.execute('insert into render_queue(minlat,maxlat,minlon,maxlon,minzoom,maxzoom) values(?,?,?,?,?,?)',(minlat,maxlat,minlon,maxlon,minzoom,maxzoom))

  conn.commit()        

def process_queue(db,map,force=False,backend="renderd"):

  from os import system

  conn = sqlite3.connect(db)
  cur = conn.cursor()
  cur.execute('select id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom from render_queue')
  list=cur.fetchall()

  for rec in list:
  
    id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom=rec
    
    if backend == "tirex" or backend == "default":    

      command = 'map='+map+ \
        ' z='+str(minzoom)+'-'+str(maxzoom)+ \
        ' lat='+str(minlat)+','+str(maxlat)+ \
        ' lon='+str(minlon)+','+str(maxlon)

      if force:
        command = 'tirex-batch -n 0 --prio=50 '+command
      else:
        command = 'tirex-batch -n 0 --prio=50 '+command+' -f not-exists'  

      print(command  )
      
      if system(command)==0:
        dcur=conn.cursor()
        dcur.execute('delete from render_queue where id=?',(id,))
        conn.commit()

    elif backend == "renderd":
    
      print(minlat,minlon,maxlat,maxlon)
    
      for zoom in range(minzoom,maxzoom+1):
        minx,miny=deg2num(minlat,minlon,zoom)
        maxx,maxy=deg2num(maxlat,maxlon,zoom)

        if minx>maxx:
          tx=minx
          maxx=minx
          minx=tx

        if miny>maxy:
          ty=miny
          maxy=miny
          miny=ty

        print(zoom,minx,miny,maxx,maxy)

        maps = map.split(',')
        
        for map_name in maps:

          command = 'render_list -a -m '+map+ \
                    ' -z '+str(zoom)+' -Z '+str(zoom)+ \
                    ' -x '+str(minx)+' -X '+str(maxx)+ \
                    ' -y '+str(miny)+' -Y '+str(maxy)
          if force:
            command = command+ ' --force'
    
          print(command  )
      
          if not system(command) == 0:
            return

      dcur=conn.cursor()
      dcur.execute('delete from render_queue where id=?',(id,))
      conn.commit()

def main():

  from optparse import OptionParser
  
  parser = OptionParser()
  parser.add_option("-d", "--data", dest="directory",
    help="Data directory", metavar="DIR")
  parser.add_option("-m", "--map", dest="map",
    help="Map name", metavar="MAP")
  parser.add_option("-z", "--zoom", dest="zoom",
    help="Maximal zoom (forced), used with coordinates pairs (minlat minlon maxlat maxlon) or filename in arguments", metavar="MAP")
  parser.add_option("-f", "--force", dest="force", 
    help="Force tile regeneration (on/off), default off")
  parser.add_option("-r", "--renderer", dest="renderer", 
    help="Rendering backend: tirex or renderd")
  (options, args) = parser.parse_args()  

  db=options.directory+'/gpx.db'
  map=options.map  
  zoom=options.zoom
  if not zoom:
    zoom=12
  force=(options.force=='on')

  if options.renderer:
    renderer=options.renderer
  else:
    print("Using default rendering backend...")
    renderer="default"

  if len(args)==1:
    filename,=args
    print("Rendering file: "+filename+"\n")
    queue_render(db,filename)
  elif len(args)==4:
    minlat,minlon,maxlat,maxlon=args
    print("Rendering region "+minlat+'..'+maxlat+' / '+minlon+'..'+maxlon+"\n")
    queue_tiles(db,float(minlat),float(minlon),float(maxlat),float(maxlon),int(zoom))

  if map:
    print("Processing map(s) "+map+"\n")
    process_queue(db,map,force,renderer)
  
if __name__ == "__main__":

  main()          
  