from django.db.models.fields import Field
from django.db.models.lookups import In
from django.db.models import Lookup
from itertools import accumulate

@Field.register_lookup
class AncestorLevelsOf(In):
    '''Find ancestors based on a level/path string in format of ie: 1_1_123_4'''
    lookup_name = 'ancestorsof'

    def get_prep_lookup(self):
        '''
        This function gets called before as_sql() and returns a value to be assigned as self.rhs.
        Split the rhs input string by "_", and returns list of all possible ancestor paths.
        '''
        levels = self.rhs.split("_")
        return list(accumulate(levels, func=lambda *i: "_".join(i)))
    
@Field.register_lookup
class SiblingLevelsOf(Lookup):
    '''Find silbings based on a level/path string in format of ie: 1_1_123_4'''
    lookup_name = 'siblingsof'

    def get_prep_lookup(self):
        '''Change the rhs to parent level'''
        nodes = self.rhs.split("_")
        return "^" + "_".join(nodes[:-1]) + "\_[^\_]+$"

    def as_postgresql(self, compiler, connection):

        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return f"{lhs} ~* {rhs}", params    
