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

"Link Class mapping to SQL table"

from django.db import models, connection
from labman2.data.models import Base
from labman2.data.models import LinkType
from labman2.data.views import class_by_name

# pylint: disable=R0904
class LinkManager(models.Manager):
    """Auxiliary class to define complex request."""

# pylint: disable=R0201
    def all_transcomm(self, ltype, subj):
        """Find list of objects linked to subj"""

        cursor = connection.cursor()
        cursor.execute("""
            WITH RECURSIVE tmp(ltype, subj, proper) AS (
                SELECT 'NaN', %s, %s
                UNION
                SELECT '', t2.subject_id, t2.property_id
                    FROM tmp t1, "Link_link" t2
                    WHERE t2.link_type_id = %s AND 
                        (t1.subj = t2.subject_id OR
                         t1.subj = t2.property_id OR
                         t1.proper = t2.subject_id OR
                         t1.proper = t2.property_id))
            SELECT DISTINCT subj FROM tmp WHERE ltype != 'NaN'
            UNION
            SELECT DISTINCT proper FROM tmp WHERE ltype != 'NaN'; """ % (
                                                        subj, subj, ltype)
            )

        result_list = [row[0] for row in cursor.fetchall()]
        return result_list
# pylint: enable=R0201

# pylint: disable=R0201
    def descendants(self, ltype, subj):
        """Finind all descendant objects"""

        cursor = connection.cursor()
        cursor.execute("""
            WITH RECURSIVE tmp(ltype, subj, proper) AS (
                SELECT link_type_id, subject_id, property_id
                FROM "Link_link" ln
                WHERE ln.link_type_id = %s AND ln.subject_id = %s
                UNION
                SELECT t2.link_type_id, t2.subject_id, t2.property_id
                FROM tmp t1, "Link_link" t2
                WHERE t2.link_type_id = %s AND t2.subject_id = t1.proper)
            SELECT subj, proper FROM tmp; """ % (ltype, subj, ltype)
            )

        result_list = [row[1] for row in cursor.fetchall()]
        return result_list
# pylint: enable=R0201

# pylint: disable=R0201
    def ascendants(self, ltype, proper):
        """Finind all ascendant objects"""

        cursor = connection.cursor()
        cursor.execute("""
            WITH RECURSIVE tmp(ltype, subj, proper) AS (
                SELECT link_type_id, subject_id, property_id
                FROM "Link_link" ln
                WHERE ln.link_type_id = %s AND ln.property_id = %s
                UNION
                SELECT t2.link_type_id, t2.subject_id, t2.property_id
                FROM tmp t1, "Link_link" t2
                WHERE t2.link_type_id = %s AND t1.subj = t2.property_id)
            SELECT subj, proper FROM tmp; """ % (ltype, proper, ltype)
            )

        result_list = [row[0] for row in cursor.fetchall()]
        return result_list
# pylint: enable=R0201
# pylint: enable=R0904


#------------------------------------------------------------------------------
class Link(Base):
    "A relation of two data entries"


    subject = models.ForeignKey(Base, related_name='+', null=True, blank=True,
                                default=None)
    property = models.ForeignKey(Base, related_name='+', null=True, blank=True,
                                 default=None)
    link_type = models.ForeignKey(LinkType, related_name='+', blank=True)

    #objects = model.Manager()
    objects = LinkManager()
    #synonym_objects = LinkSynonymManager()

    def __unicode__(self):

# pylint: disable=E1101
        subj = class_by_name(self.subject.classname.classname).objects.get(
                                id=self.subject.id) if self.subject else None
        proper = class_by_name(self.property.classname.classname).objects.get(
# pylint: disable=E1101
                                id=self.property.id) if self.property else None
        return u'%s (%s - %s): %s' % (
                            self.link_type.link_type,
                            subj, proper, Base.__unicode__(self))

    def show_details(self):
        "Long representation"

        info_dict = [('LinkType', self.link_type),
                     ('Subject', self.subject),
                     ('Property', self.property)] # pylint: disable=E1101
        info_dict.extend(Base.show_details(self))

        return info_dict
