import Data.Char
import Data.List
import Test.QuickCheck

-- 1

findIndex :: Eq a => a -> [a] -> Int
findIndex a as = head $ 0:[i | (a',i) <- zip as [0..], a==a']

-- 2

extension :: String -> String
extension = ('.':) . reverse . takeWhile (/= '.') . reverse

-- 3

data Store
  = Empty
  | Join Int Store Store

size :: Store -> Int
size Empty = 0
size (Join _ s1 s2) = 1 + size s1 + size s2

-- 4

prop_length_append :: [Int] -> [Int] -> Bool
prop_length_append xs ys =
    length (xs ++ ys) == length xs + length ys

prop_length_append2 :: [Int] -> [Int] -> Bool
prop_length_append2 xs ys =
    length (xs ++ ys) == length (ys ++ xs)
  -- Somewhat strange property, but fulfills the assignment

-- 5

initFile :: IO ()
initFile = do
    name    <- getLine
    content <- getLine
    writeFile name content


----------------------------------------------------------------------------------------------------
-- 6

data Command
  = FORW Int
  | BACKW Int
  | LEFT
  | RIGHT
  deriving (Eq, Show)

data Dir = North | South | West | East

move :: Dir -> Int -> (Int,Int) -> (Int,Int)
move North l (x,y) = (x,y+l)
move South l (x,y) = (x,y-l)
move West  l (x,y) = (x-l,y)
move East  l (x,y) = (x+l,y)

turnLeft :: Dir -> Dir
turnLeft North = West
turnLeft South = East
turnLeft West  = South
turnLeft East  = North

turnRight :: Dir -> Dir
turnRight North = East
turnRight South = West
turnRight West  = North
turnRight East  = South

destination :: [Command] -> (Int,Int)
destination = go North (0,0)
  where
    go _ pos [] = pos
    go d pos (i:is) = case i of
      FORW  l -> go d (move d l    pos) is
      BACKW l -> go d (move d (-l) pos) is
      LEFT    -> go (turnLeft  d) pos is
      RIGHT   -> go (turnRight d) pos is

test1 = destination [FORW 20, BACKW 10, RIGHT, FORW 100]
test2 = destination [FORW 20, BACKW 5, LEFT, FORW 100]



----------------------------------------------------------------------------------------------------
-- 6 (alternative)

forward :: Int -> (Int,Int) -> (Int,Int)
forward l (x,y) = (x,y+l)

rotLeft,rotRight :: (Int,Int) -> (Int,Int)
rotLeft  (x,y) = (-y,x)
rotRight (x,y) = (y,-x)

destination2 :: [Command] -> (Int,Int)
destination2 [] = (0,0)
destination2 (i:is) = case i of
  FORW l  -> forward l    (destination2 is)
  BACKW l -> forward (-l) (destination2 is)
  LEFT    -> rotLeft      (destination2 is)
  RIGHT   -> rotRight     (destination2 is)

instance Arbitrary Command
  where
    arbitrary = oneof
      [ fmap FORW arbitrary
      , fmap BACKW arbitrary
      , return LEFT
      , return RIGHT
      ]

prop_destination cs = destination cs == destination2 cs



----------------------------------------------------------------------------------------------------
-- 7

type Doc = [DocPart]

data DocPart
  = Text String
  | Tag String Doc

wordsDoc :: Doc -> [String]
wordsDoc = concatMap wordsPart

wordsPart :: DocPart -> [String]
wordsPart (Text s)  = words s
wordsPart (Tag _ d) = wordsDoc d

importantHTML :: Doc -> [String]
importantHTML = concatMap importantPart

importantPart :: DocPart -> [String]
importantPart (Text s)     = []
importantPart (Tag "EM" d) = wordsDoc d
importantPart (Tag _    d) = importantHTML d

annasSida :: Doc
annasSida =
  [ Text "Welcome to my website!"
  , Tag "P" [ Tag "B" [ Text "My hobbies are "
                      , Tag "EM" [ Text "Haskell" ]
                      , Text " programming and playing "
                      , Tag "EM" [ Text "Myst" ]
                      , Text "."
                      ] ]
  , Tag "P" [ Text "Thanks for visiting! "
            , Tag "EM" [ Text "anna@gmail.com" ]
            ]
  ]