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

import random
import sys

import kivy

from kivy.app import App
from kivy.uix.widget import Widget

from kivy.core.window import Window
from kivy.core.audio import SoundLoader
from kivy.clock import Clock
# from kivy.config import Config

from kivy.uix.button import Button

from kivy.properties import NumericProperty, ObjectProperty


PLATFORM = kivy.platform

if PLATFORM is not 'android':
    # pass
    Window.size = (1100, 650)


FPS = 1.0 / 60.0
FACTOR = Window.width // 12
GAME_SPEED = Window.width / 315
BEZIER_PRECISION = 0.2


class FlyingObject(Widget):

    ''' Coins and floating islands'''

    def __init__(self, pos=None, speed_factor=1):
        super(FlyingObject, self).__init__()
        self.speed_factor = speed_factor

        if not pos:
            interval = (0, int(Window.height - self.height))
            pos = Window.width, random.randint(*interval)

        # print pos
        self.pos = pos

        Clock.schedule_interval(self._move, FPS)

    def _move(self, *args):
        if self.right <= 0:
            self.parent.remove_widget(self)
            return False

        self.x -= self.speed_factor * self.parent.get_game_speed()

    def __del__(self):
        print 'Object %s deleted' % self


class Coin(FlyingObject):

    ''' Coin. Main points currency'''
    factor = NumericProperty(FACTOR)


class FloatingIsland(FlyingObject):

    '''Main obstacle.'''

    factor = NumericProperty(FACTOR)


class Hero(Widget):

    '''Main character class.'''

    factor = NumericProperty(FACTOR)
    speed = NumericProperty(0)

    def __init__(self):
        super(Hero, self).__init__()
        Clock.schedule_interval(self.__move, FPS)

    def __up(self, *args):
        if self.speed > 1.1 * self.parent.speed:
            return

        self.speed += 0.2

    def __down(self, *args):
        if self.speed < -1.3 * self.parent.speed:
            return
        self.speed -= 0.22

    def __lose_life(self):
        pass

    def __jump(self, bottom=False):
        if bottom:
            self.__lose_life()

        # self.speed = 2 * self.parent.speed
        self.up()

    def __move(self, *args):
        # print self.speed, 1.1 * self.parent.speed, -1.3 * self.parent.speed
        if self.top <= 0:
            self.__jump(bottom=True)
        elif self.y >= Window.height + self.height:
            self.down()
        self.y += self.speed * self.parent.speed

    def up(self):
        Clock.unschedule(self.__down)
        Clock.schedule_interval(self.__up, FPS)

    def down(self):
        Clock.unschedule(self.__up)
        Clock.schedule_interval(self.__down, FPS)


class Game(Widget):

    '''Deals with gravity, movement, collisions, schedule'''

    speed = NumericProperty()
    factor = NumericProperty(FACTOR)

    def __nn(self, s):
        pass

    def __mm(self, sad):
        print Clock.get_rfps()

    def __test(self, asd=None):
        a = [(random.randint(self.width, 2 * self.width), random.randint(0, self.height)) for _ in range(4)]
        a = self.__bezier(a)

        for x in range(3):
            self.add_widget(FloatingIsland())

        for x in a:
            self.add_widget(Coin(x))

        Clock.schedule_once(self.__test, 2)

        # self.__stop_time()

    @staticmethod
    def __bezier(points, precision=BEZIER_PRECISION):
        assert len(points) == 4 and precision < 1, len(points)
        coords = []

        t = precision
        while t <= 1:
            x = [((1 - t) ** 3) * points[0][0],
                 3 * t * ((1 - t) ** 2) * points[1][0],
                 3 * (t ** 2) * (1 - t) * points[2][0],
                 (t ** 3) * points[3][0]]
            y = [((1 - t) ** 3) * points[0][1],
                 3 * t * ((1 - t) ** 2) * points[1][1],
                 3 * (t ** 2) * (1 - t) * points[2][1],
                 (t ** 3) * points[3][1]]
            coords.append((int(sum(x)), int(sum(y))))
            t += precision
        return coords

    def __increase_speed(self, timing):
        if self.speed >= GAME_SPEED:
            self.speed = GAME_SPEED
            return False
        self.speed += 0.5

    def __decrease_speed(self, arg=None):
        if self.speed <= 0:
            Clock.schedule_interval(self.__increase_speed, 0.1)
            return False
        self.speed -= 0.5

    def __stop_time(self):
        interval_time = 0.1
        Clock.schedule_interval(self.__decrease_speed, interval_time)

    def on_touch_down(self, touch):
        if touch.is_double_tap:
            self.__stop_time()
            # self.__decrease_speed()
        self.hero.up()

    def on_touch_up(self, touch):
        self.hero.down()

    def get_game_speed(self):
        return self.speed

    def start(self):
        self.size = Window.size
        self.speed = GAME_SPEED
        self.hero = Hero()
        self.add_widget(self.hero)
        self.__test()
        Clock.schedule_interval(self.__mm, 1)


class YetApp(App):

    '''Just starts the game and clocks. Adds label'''

    def build(self):
        # Window.fullscreen = True
        game = Game()
        game.start()
        return game


if __name__ == '__main__':
    '''Simple game. Almost identical to The Shortest Story from WinPhone'''

    YetApp().run()
