import ugfx

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __str__(self):
        return "(%f,%f)"%(self.x,self.y)

class Line:
    def __init__(self, points, t):
        self.points = points
        self.transform = t

    def draw_line(self):
        p1 = self.points[0]
        for p2 in self.points:
            ugfx.line(int(p1.x),int(p1.y),
                      int(p2.x),int(p2.y), ugfx.BLACK)
            p1 = p2

    def draw_cline(self):
        p1 = self.points[0]
        for p2 in self.points:
            ugfx.line(int(p1.x+self.transform.x),
                      int(p1.y+self.transform.y),
                      int(p2.x+self.transform.x),
                      int(p2.y+self.transform.y),
                      ugfx.BLACK)
            p1 = p2

class Figure:
    def __init__(self, lines):
        self.lines=lines

    def draw_tiled(self):
        for l in self.lines:
            p1 = l.points[0]
            for p2 in l.points:
                for sx in [120,140,160,180,200,220,240,260,280]:
                    for sy in [-10,10,30,50,70,90,110]:
                        x1 = sx+p1.x*0.25
                        y1 = sy+p1.y*0.25
                        x2 = sx+p2.x*0.25
                        y2 = sy+p2.y*0.25
                        ugfx.line(int(x1),int(y1),
                                  int(x2),int(y2),
                                  ugfx.BLACK)
                p1 = p2


    def draw_figure(self):
        for l in self.lines:
            l.draw_line()
            l.draw_cline()

class Editor:

    width = 296
    height = 128

    def __init__(self):
        self.figure = Figure([Line([Point(20.0,20.0),Point(20.0,100.0)],
                                   Point(80.0,0.0)),
                              Line([Point(20.0,100.0),Point(100.0,100.0)],
                                   Point(0.0,-80.0))])
        self.linenr = 0
        self.pointnr = 0
        self.pos = Point(0.0, 0.0)
        self.mode = 0

    def draw_cursor(self):
        startpoint=self.figure.lines[self.linenr].points[self.pointnr]
        cpoint = Point(startpoint.x+self.pos.x,
                       startpoint.y+self.pos.y)
        ugfx.line(int(cpoint.x), int(cpoint.y-5),
                  int(cpoint.x), int(cpoint.y+5), ugfx.BLACK)
        ugfx.line(int(cpoint.x-5), int(cpoint.y),
                  int(cpoint.x+5), int(cpoint.y), ugfx.BLACK)

        transform = self.figure.lines[self.linenr].transform
        startpoint = Point(startpoint.x+transform.x,
                           startpoint.y+transform.y)
        cpoint = Point(startpoint.x+self.pos.x,
                       startpoint.y+self.pos.y)
        ugfx.line(int(cpoint.x), int(cpoint.y-5),
                  int(cpoint.x), int(cpoint.y+5), ugfx.BLACK)
        ugfx.line(int(cpoint.x-5), int(cpoint.y),
                  int(cpoint.x+5), int(cpoint.y), ugfx.BLACK)

    def move_up(self):
        if self.mode == 0:
            self.move_y(-1.0)
        else:
            self.pos.y -= 1

    def move_down(self):
        if self.mode == 0:
            self.move_y(1.0)
        else:
            self.pos.y += 1

    def move_left(self):
        if self.mode == 0:
            self.move_x(-1.0)
        else:
            self.pos.x -= 1

    def move_right(self):
        if self.mode == 0:
            self.move_x(1.0)
        else:
            self.pos.x +=1

    def move_next(self):
        if self.pointnr<len(self.figure.lines[self.linenr].points)-2:
            self.pointnr += 1
            self.pos = Point(0.0, 0.0)
        else:
            if self.linenr<len(self.figure.lines)-1:
                self.linenr +=1
                self.pointnr = 0
                self.pos = Point(0.0, 0.0)
            else:
                self.pointnr = 0
                self.pos = Point(0.0, 0.0)
                self.move_previous()

    def move_previous(self):
        if self.pointnr>0:
            self.pointnr -= 1
            startpoint=self.figure.lines[self.linenr].points[self.pointnr]
            endpoint=self.figure.lines[self.linenr].points[self.pointnr+1]
            dx = endpoint.x - startpoint.x
            dy = endpoint.y - startpoint.y
            self.pos = Point(dx, dy)
        else:
            if self.linenr>0:
                self.linenr-=1
                self.pointnr=len(self.figure.lines[self.linenr].points)-2
                startpoint=self.figure.lines[self.linenr].points[self.pointnr]
                endpoint=self.figure.lines[self.linenr].points[self.pointnr+1]
                dx = endpoint.x - startpoint.x
                dy = endpoint.y - startpoint.y

                self.pos = Point(dx,dy)
            else:
                pass
                ### TODO

    def move_y(self,step):
        startpoint=self.figure.lines[self.linenr].points[self.pointnr]
        endpoint=self.figure.lines[self.linenr].points[self.pointnr+1]
        dx = endpoint.x - startpoint.x
        dy = endpoint.y - startpoint.y
        if dy==0 or (self.pos.y+step)<0 or (self.pos.y+step)>dy:
            pass
        else:
            self.pos.y += step
            self.pos.x = self.pos.y*(dx/dy)

        if self.pos.y==dy and self.pos.x==dx:
            self.move_next()
        elif self.pos.y==0 and self.pos.x==0:
            self.move_previous()

    def move_x(self, step):
        startpoint=self.figure.lines[self.linenr].points[self.pointnr]
        endpoint=self.figure.lines[self.linenr].points[self.pointnr+1]
        dx = endpoint.x - startpoint.x
        dy = endpoint.y - startpoint.y
        if dx==0 or (self.pos.x+step)<0  or (self.pos.x+step)>dx:
            pass
        else:
            self.pos.x += step
            self.pos.y = self.pos.x*(dy/dx)

        if self.pos.y==dy and self.pos.x==dx:
            self.move_next()
        elif self.pos.y==0 and self.pos.x==0:
            self.move_previous()

    def breakline(self):
        startpoint=self.figure.lines[self.linenr].points[self.pointnr]
        dx = self.pos.x + startpoint.x
        dy = self.pos.y + startpoint.y
        breakpoint = Point(dx,dy)
        self.pointnr +=1
        self.figure.lines[self.linenr].points.insert(self.pointnr,breakpoint)
        self.pos = Point(0.0, 0.0)

    def draw_editor(self):
        ugfx.clear(ugfx.WHITE)
        self.figure.draw_figure()
        self.draw_cursor()
        self.figure.draw_tiled()
        ugfx.flush()

e = Editor()
def up(pushed):
    if pushed:
        e.move_up()
        e.draw_editor()

def down(pushed):
    if pushed:
        e.move_down()
        e.draw_editor()

def left(pushed):
    if pushed:
        e.move_left()
        e.draw_editor()

def right(pushed):
    if pushed:
        e.move_right()
        e.draw_editor()

def mode_switch(pushed):
    if pushed:
        if e.mode == 0:
            e.mode=1
        else:
            e.breakline()
            e.draw_editor()
            e.mode=0

def tessellate(pushed):
    if pushed:
        e.draw_tiled()

ugfx.init()
ugfx.input_init()
ugfx.clear(ugfx.BLACK)
ugfx.flush()
ugfx.clear(ugfx.WHITE)
ugfx.flush()


ugfx.input_attach(ugfx.JOY_UP, up)
ugfx.input_attach(ugfx.JOY_UP, up)
ugfx.input_attach(ugfx.JOY_DOWN, down)
ugfx.input_attach(ugfx.JOY_LEFT, left)
ugfx.input_attach(ugfx.JOY_RIGHT, right)
ugfx.input_attach(ugfx.BTN_A, mode_switch)

#while True:
e.draw_editor()