from django.db.models.query import Q as DjangoQ
from django.utils.datastructures import SortedDict


def replaceDict(string, dict):
    " Will take a dictioary and an arbitrary string, and replace the string with the dictioary."
    if len(dict) == 0:
        return string

    curDict = dict.copy()
    keys = curDict.keys()
    keys.sort(lambda x,y: cmp(len(y), len(x)))
    key = keys[0]
    val = curDict[key]

    del curDict[key]

    offset  = 0
    strings = [string]


    while strings[-1].find(key) != -1:
        loc = strings[-1].find(key)

        strings.append(strings[-1][len(key) + loc:])

        strings[-2] = strings[-2][:loc]


    return val.join([replaceDict(s,curDict) for s in strings])




class QSplit(DjangoQ):
    " Encapsulates a single JOIN-type query into one object "

    def __init__(self, q):
        " Creates a single Q-ish object that separates itself from other Q objects. "
        self.q = q

    def get_sql(self, opts):
        " This will generate the correct (joins, where, params) tuple. "
        from django.conf import settings

        engine_lower = settings.DATABASE_ENGINE.lower()

        if 'mysql' in engine_lower:
            tick = '`'
        elif 'postgres' in engine_lower or 'sqlite' in engine_lower:
            tick = '"'
        else:
            tick = '"'

        joins, where, params = self.q.get_sql(opts)
        key_replace = {}
        joins2      = SortedDict()
        where2      = []


        for key, val in joins.items():
            cur_key = key.strip(tick)
            cur_val = '%s__%s' % (key.strip(tick), hash(self))

            key_replace[cur_key] = cur_val

            joins2['%s%s%s' % (tick, cur_val, tick)] = val



        for key, val in joins2.items():
            joins2[key] = (val[0],val[1],replaceDict(val[2],key_replace))


        where2 = [replaceDict(clause, key_replace) for clause in where]
        return joins2, where2, params