import numpy as np


class LineArgs:
    '''Model linky aproximovany polynomialni funkci
    '''
    def __init__(self, left_x, y_list, i, j):
        self.polargs = (np.polyfit(range(left_x, left_x + len(y_list)), y_list, 3))
        self.left_x = left_x
        self.right_x = left_x + len(y_list)
        self.avg_y = y_list[0]
        self.staff = i
        self.line = j

class Lines:
    '''Datova struktura pro vsechny detekovane linky
    '''
    def __init__(self, linelist, staffline_height, staffspace_height):
        self.staffline_height = staffline_height
        self.staffspace_height = staffspace_height
        self.maxstaff = len(linelist)
        self.maxlines = len(linelist[0])
        self.lineargs = []
        self.linenum = 5
        for i, lines in enumerate(linelist):
            for j, sublines in enumerate(lines):
                self.lineargs.append(LineArgs(sublines.left_x, sublines.y_list, i, j))


    @staticmethod
    def checkLines(linelist):
        '''Overuje zda je pocet detekovanych linek na radku roven 5
        
        checkerr - pocet chybnych radku
        '''
        for staves in linelist:
            checkerr = checkerr + len(staves) - 5
        return checkerr


    def touch(self, point, staff=None):
        '''Datova struktura pro detekci vzdalenosti mezi linkou a bodem
        
        return[0] - cislo radku nejblizsi detekovane linky
        
        return[1] - cislo linky nejblizsi detekovane linky
        
        return[2] - vzdalenost od nejblizsi detekovane linky
        '''
        if staff is None:
            args = self.lineargs
        else:
            args = [x for x in self.lineargs if x.staff == staff]
        distance = [[i, (point[1] - np.polyval(line.polargs, point[0]))] for i, line in enumerate(args)]
        #sort = sorted(range(len(self.distance)), key=lambda x: abs(self.distance[x]))
        minline = min(distance, key=lambda x: abs(x[1]))
        return [self.lineargs[minline[0]].staff, self.lineargs[minline[0]].line, minline[1]]

    def finder(self, y):
        '''Rychlejsi detekce vzdalenosti mezi linkou a bodem
        
        return[0] - odsazeni nejblizsi linky
        
        return[1] - prumerna poloha linky v ose y
        '''
        minline = min(self.lineargs, key=lambda x: abs(y - x.avg_y))
        return [minline.left_x, minline.avg_y]
