import SOEGraphics hiding (Region)
import qualified SOEGraphics as G (Region)
import Picture
import Animation
import Time

--- #1

clock :: Int -> Int -> Int  -> Animation Graphic
clock initHours initMinutes initSeconds = 
      picToGraphic . clockPic
   where 
     clockPic t = secondHand t `Over` minuteHand t `Over` hourHand t `Over` tickMarks `Over` face
     face = Region Yellow (Shape (Ellipse radius radius))
     tickMarks = Region Magenta $ foldr Union Empty [positionAt angle 1.0 square | h <- [1..12], let angle = h/12 * 2 * pi]
     secondHand = hand Red 1 60
     minuteHand = hand Green 0.8 (60*60)
     hourHand = hand Blue 0.6 (12*60*60)
     hand color radiusRatio divisions t = Region color (positionAt angle radiusRatio dot)
	  where angle = fromIntegral (round (initTime + t) `mod` divisions) / (fromIntegral divisions) * 2 * pi
-- continuous:
--	  where angle = (initTime + t) / (fromInt divisions) * 2 * pi
     initTime = fromIntegral $ (initHours * 60 * 60) + (initMinutes * 60) + initSeconds
     positionAt angle radiusRatio = Translate (radius * radiusRatio * sin angle, radius * radiusRatio * cos angle) 
     dot = Shape (Ellipse (radius/20) (radius/20))
     square = Shape (Rectangle (radius/10) (radius/10))
     radius = 2.0

main :: IO ()
main = 
  do clt <- getClockTime
     calt <-  toCalendarTime clt
     animate "clock" (clock (ctHour calt) (ctMin calt) (ctSec calt))

-- # 2

type Poly a = [a] -- stream

scale :: Num a => a -> Poly a -> Poly a
scale a = map (*a)

addPoly :: Num a => Poly a -> Poly a -> Poly a
addPoly = zipWith (+)

subPoly :: Num a => Poly a -> Poly a -> Poly a
subPoly = zipWith (-)

mulPoly :: Num a => Poly a -> Poly a -> Poly a
mulPoly (a:as') bs = addPoly (scale a bs) (0:(mulPoly as' bs))

divPoly :: Fractional a => Poly a -> Poly a -> Poly a
divPoly (a:as') bs@(b:bs') = ab0:(divPoly (subPoly as' (scale ab0 bs')) bs)
         where ab0 = a / b 

toPoly :: Num a => [a] -> Poly a
toPoly as = as ++ (repeat 0)

newtype P a = P {unP::[a]}

toP :: Num a => [a] -> P a
toP as = P (toPoly as) 

instance Eq (P a) where
  (P as) == (P bs) = error "== not defined on polynomials"

instance Show a => Show (P a) where
  show (P as) = show as

instance Num a => Num (P a) where
  (P as) + (P bs) = P (addPoly (toPoly as) (toPoly bs))
  (P as) - (P bs) = P (subPoly (toPoly as) (toPoly bs))
  (P as) * (P bs) = P (mulPoly (toPoly as) (toPoly bs))
  fromInteger i = P (toPoly [fromInteger i])
 
instance Fractional a => Fractional (P a) where
  (P as) / (P bs) = P (divPoly (toPoly as) (toPoly bs))
  fromRational r = P (toPoly [fromRational r])

fibs = take 10 (unP (1 / toP [1,-1,-1]))


