#!/usr/bin/env python2.5
# -*- coding: utf-8 -*-

import sys
import os

import pygame
from pygame.locals import *
import time

import struct
import fcntl

#Set as early as wanted, will make sure that the "Loading..." banner disappers
#Only needed because this is a pure pygame app right now, wouldn't be needed when using GTK!
os.environ["SDL_VIDEO_X11_WMCLASS"]="moodlight"


EVT_STEP = pygame.USEREVENT

width = 800
height = 480

canvas = pygame.Surface((width, height))
canvas.fill(Color("black"))

path = '/usr/share/moodlight'
   
#################################################
# Class that handles all display stuff
#################################################
class display:
 currenthue = 128
 userbrightness = 255
 def __init__(self):
  pygame.init()
  pygame.mixer.quit() # we don't want pygame hogging the audio device (from KAGU, don't know if it matters here)
  pygame.mouse.set_visible(False)

  pygame.display.set_caption("moodlight")
  self.scale = False
  self.screen = pygame.display.set_mode((width,height),FULLSCREEN)

  global s1
  s1 = pygame.Surface((1, 48))
  global c1
  #c1 = Color("black")
  c1 = Color("#2e2c2d")
  for w in range(0, 691):
    col1 = hsvToRGB(int(360.0/692*w), 1.0, 1.0)
    col1hex = "#%02x%02x%02x" % (int(col1[0]*255), int(col1[1]*255), int(col1[2]*255))
    c1 = Color(col1hex)
    s1.fill(c1)
    self.screen.blit(s1,(w,2))

  #Flashlight mode button
  s2 = pygame.Surface((48, 54))  
  s2.fill(Color("white"))
  self.screen.blit(s2,(703,0))
  #Close button
  timeFont = pygame.font.Font(None,  48)
  textX = timeFont.render("X", 1, (128, 192, 128, 128))
  self.screen.blit(textX, (764,8))

  guiIcon = pygame.image.load(os.path.join(path,"gui.png")).convert_alpha() 
  self.screen.blit(guiIcon,(692,0))

    
#################################################
 def show(self):
 
  #TODO: reset brightness to stored value
  s2 = pygame.Surface((width, height-54))
  c2 = Color("black")
  
  col2 = hsvToRGB(d.currenthue, 1.0, 1.0)
  col2hex = "#%02x%02x%02x" % (int(col2[0]*255), int(col2[1]*255), int(col2[2]*255))
  c2 = Color(col2hex)
  s2.fill(c2)  
  self.screen.blit(s2,(0,53))

  pygame.display.flip()

 def white(self):

  #TODO: set brightness to maximum value 
  s2 = pygame.Surface((width, height-54))
  c2 = Color("white") 
  s2.fill(c2)  
  self.screen.blit(s2,(0,53))

  pygame.display.flip()
    
#Display
#################################################

#Color conversion implemented, as pymaemo used to contain only pygame 1.7.1
#From http://code.activestate.com/recipes/576554/
def hsvToRGB(h, s, v):
    """Convert HSV color space to RGB color space
    
    @param h: Hue
    @param s: Saturation
    @param v: Value
    return (r, g, b)  
    """
    import math
    hi = math.floor(h / 60.0) % 6
    f =  (h / 60.0) - math.floor(h / 60.0)
    p = v * (1.0 - s)
    q = v * (1.0 - (f*s))
    t = v * (1.0 - ((1.0 - f) * s))
    return {
        0: (v, t, p),
        1: (q, v, p),
        2: (p, v, t),
        3: (p, q, v),
        4: (t, p, v),
        5: (v, p, q),
    }[hi]

#################################################
def quit():
 #TODO: reset brightness to stored value
 exit()

#################################################
 
class Leds:
  # stolen from /usr/include/linux/video*
  V4L2_CTRL_CLASS_CAMERA=0x009a0000
  V4L2_CID_CAMERA_CLASS_BASE=V4L2_CTRL_CLASS_CAMERA | 0x900
  V4L2_CID_TORCH_INTENSITY=V4L2_CID_CAMERA_CLASS_BASE+16
  VIDIOC_S_CTRL = 0xc008561c
  control = struct.pack("Ii", V4L2_CID_TORCH_INTENSITY, 1)

  def __init__(self):
    self.video = None

  def on(self):
    if not self.video:
      self.video = file("/dev/video0", 'w')
      videofd = self.video.fileno()
      fcntl.ioctl(videofd, self.VIDIOC_S_CTRL, self.control)

  def off(self):
    pass
    if self.video:
      self.video.close()
      self.video = None


################################################# 
def main():

 global d
 d = display()
 d.currenthue = 128
 d.show()

 pygame.time.set_timer(EVT_STEP, 100)
 clock = pygame.time.Clock() 
 
 leds = Leds()
 flashlightClickCount = 0

 #TODO: read brightness from stored value and store in d.userbrightness

 # Wait for user input
 while True:
  event = pygame.event.wait() #While the program is waiting it will sleep in an idle state
  #Mouse events
  if (event.type == MOUSEBUTTONDOWN):        #Touchscreen-Event
   pos = pygame.mouse.get_pos()
   pygame.time.set_timer(EVT_STEP, 0)
   #print pos[0],pos[1]

   #Quit button
   if pos[0]>=740 and pos[1]<=53:
     quit()

   #Flashlight mode
   elif pos[0]>=692 and pos[0]<740 and pos[1]<=53:
     d.white()
     flashlightClickCount += 1
     if flashlightClickCount % 2 == 0:
       leds.on()
     else:
       leds.off()

   #Color/speed
   else:
     flashlightClickCount = 0
     leds.off()
     hue =  int(360.0/(width-108)*pos[0])
     if hue<0:
       hue=0
     d.currenthue = hue
     d.show()
     #Range 0 (in colorbar) to 100 (speedy) to 3000
     speed = 100
     if pos[1]<=48:
       speed = 0
     else:
        #Position values: 48-480, Range = 432,  use this (doubled) as ms for timer
       speed = 2*(480-pos[1]+5)
       #print "Speed = ms " + str(speed)
     pygame.time.set_timer(EVT_STEP, speed)

  #Key events (mainly for debugging, not mandatory on final device)
  if (event.type == KEYUP):
    if (event.key != K_ESCAPE):             # Not ESC? Switch to flaslight mode
      #d.show()
     pygame.time.set_timer(EVT_STEP, 0)    
     d.white()
    else:                                   # K_ESCAPE Esc/Back button -> Exit
      quit()
  if (event.type == EVT_STEP):          #Timer-Event
   d.currenthue = d.currenthue + 1
   if d.currenthue > 359:
    d.currenthue = 0
   d.show()
  #clock.tick(30) 

#################################################      
if __name__ == '__main__':
 main()


