#! /usr/bin/env ppython
# -*- coding: utf-8 -*-

import sys
import os
import math

from pandac.PandaModules import loadPrcFile, loadPrcFileData
loadPrcFileData('','audio-library-name null')
loadPrcFileData('','win-size 1024 576')
#loadPrcFileData('','undecorated #t')
loadPrcFileData('','win-origin 100 100')

import direct.directbase.DirectStart
from direct.showbase import DirectObject
from direct.gui.OnscreenImage import OnscreenImage
from panda3d.core import MeshDrawer
from pandac.PandaModules import *



# Make the escape key work...
class EscExit(DirectObject.DirectObject):
  def __init__(self):
    self.accept('escape',self.exit)

  def exit(self):
    saveData()
    sys.exit()

escExit = EscExit()



# Move to the directory of the script...
scriptDir = os.path.abspath(os.path.dirname(sys.argv[0]))
os.chdir(scriptDir)



# Get a list of filenames in the directory with .png or .jpg extensions...
files = os.listdir('.')
files = filter(lambda f: f[-3:].lower()=='jpg' or f[-3:].lower()=='png',files)
print files



# Setup the initial state...
fileID = 0
imageNode = OnscreenImage(files[fileID], parent=render2d)


leftCorner = (-0.5,0.0)
rightCorner = (0.5,0.0)
eyebrow = (0.0,0.4)
centre = (0.0,0.0)
radius = 0.25

# Saving and loading code for the parameters...
def saveData():
  fn = files[fileID][:-3] + 'epd'
  f = open(fn,'w')
  f.write('filename = "'+files[fileID]+'"\n')
  f.write('leftCorner = '+str(leftCorner)+'\n')
  f.write('rightCorner = '+str(rightCorner)+'\n')
  f.write('eyebrow = '+str(eyebrow)+'\n')
  f.write('centre = '+str(centre)+'\n')
  f.write('radius = '+str(radius)+'\n')

def loadData():
  fn = files[fileID][:-3] + 'epd'
  try:
    exec(open(fn,'r')) in globals()
  except:
    pass



# Arrange for image switching...
class ImageSwitch(DirectObject.DirectObject):
  def __init__(self):
    self.accept('arrow_left',self.left)
    self.accept('arrow_right',self.right)

  def left(self):
    global fileID
    global files
    saveData()
    fileID = (fileID+len(files)-1)%len(files)
    self.reloadImage()

  def right(self):
    global fileID
    global files
    saveData()
    fileID = (fileID+1)%len(files)
    self.reloadImage()

  def reloadImage(self):
    global fileID
    global files
    global imageNode
    imageNode.destroy()
    print files[fileID]
    imageNode = OnscreenImage(files[fileID], parent=render2d)

    loadData()

imageSwitch = ImageSwitch()



# Mouse click handler...
class ClickHandler(DirectObject.DirectObject):
  def __init__(self):
    self.accept('mouse1',self.lmb)

  def lmb(self):
    global leftCorner
    global rightCorner
    global eyebrow
    global centre
    global radius
    # Get coordinates...
    mpos = base.mouseWatcherNode.getMouse()
    x = mpos.getX()*(16.0/9.0)
    y = mpos.getY()
    print 'x,y =',x,y

    # Work out which entity its closest to - the circle or one of the end points...
    circleDist = abs(math.sqrt((x-centre[0])**2 + (y-centre[1])**2)-radius)
    leftDist = math.sqrt((x-leftCorner[0])**2 + (y-leftCorner[1])**2)
    rightDist = math.sqrt((x-rightCorner[0])**2 + (y-rightCorner[1])**2)
    eyebrowDist = math.sqrt((x-eyebrow[0])**2 + (y-eyebrow[1])**2)

    if circleDist < min((leftDist,rightDist,eyebrowDist)):
      nx = x - centre[0]
      ny = y - centre[1]
      nLen = math.sqrt(nx*nx + ny*ny)
      nx /= nLen
      ny /= nLen

      ox = centre[0] - nx*radius
      oy = centre[1] - ny*radius

      centre = (0.5*(ox+x),0.5*(oy+y))
      radius = 0.5*math.sqrt((ox-x)**2 + (oy-y)**2)
    elif leftDist < min((rightDist,eyebrowDist)):
      leftCorner = (x,y)
    elif rightDist < eyebrowDist:
      rightCorner = (x,y)
    else:
      eyebrow = (x,y)



# State renderer...
md = MeshDrawer()
md.setBudget(256)
mdNode = md.getRoot()
mdNode.reparentTo(aspect2d)
mdNode.setDepthWrite(False)
mdNode.setTransparency(True)
mdNode.setTwoSided(True)
mdNode.setBin("fixed",0)
mdNode.setLightOff(True)

def renderLines(task):
  global leftCorner
  global rightCorner
  global eyebrow
  global centre
  global radius
  global md
  md.begin(base.cam,aspect2d)

  md.segment(Vec3(leftCorner[0],0.1,leftCorner[1]), Vec3(rightCorner[0],0.1,rightCorner[1]), Vec4(0.0,0.0,1.0,1.0), 0.005, Vec4(0.0,1.0,0.0,1.0))

  for i in xrange(33):
    ang = math.pi*2.0*float(i)/32.0
    x = centre[0] + math.sin(ang)*radius
    y = centre[1] + math.cos(ang)*radius
    md.linkSegment(Vec3(x,0.2,y), Vec4(0.0,0.0,1.0,1.0), 0.005, Vec4(0.0,0.0,1.0,1.0))
  md.linkSegmentEnd(Vec4(0.0,0.0,1.0,1.0), Vec4(0.0,0.0,1.0,1.0))

  md.billboard(Vec3(eyebrow[0],0.3,eyebrow[1]), Vec4(0.0,0.0,1.0,1.0), 0.01, Vec4(0.0,1.0,1.0,1.0))

  md.end()
  return task.cont
taskMgr.add(renderLines,'renderLines')
    

clickhandler = ClickHandler()


# Run the application...
run()
