'''
Created on Nov 10, 2014

@author: chorton
'''

from collections import namedtuple
import itertools
import collections
import csv
import json
import logging
from operator import attrgetter, itemgetter

log = logging.getLogger(__name__)


class Ticket(namedtuple('Ticket', 'section, row, seats, price, barcodes, listing_id, action')):
    
    __slots__ = ()
    
    def __eq__(self, item):
        # override to exclude listing_id & action from comparison
        a = (self.section, self.row, self.seats, self.price, self.barcodes)
        b = (item.section, item.row, item.seats, item.price, item.barcodes)
        return a == b
    
    def __ne__(self, item):
        # override to exclude listing_id & action from comparison
        a = (self.section, self.row, self.seats, self.price, self.barcodes)
        b = (item.section, item.row, item.seats, item.price, item.barcodes)
        return a != b
    
    def __gt__(self, item):
        # override to evaluate if item.seats is a subset of self.seats
        a = (self.section, self.row, self.seats, self.price)
        b = (item.section, item.row, item.seats, item.price)
        return a > b

    def __lt__(self, item):
        # override to evaluate if self.seats is a subset of item.seats
        a = (self.section, self.row, self.seats, self.price)
        b = (item.section, item.row, item.seats, item.price)
        return a < b

    def __ge__(self, item):
        # override to combine gt or eq results
        return self == item or self > item
    
    def __le__(self, item):
        # override to combine lt or eq results
        return self == item or self < item

    def subset(self, item):
        return (self != item and
                self.section == item.section and
                self.row == item.row and
                set(self.seats).issubset(set(item.seats)))

    def superset(self, item):
        return (self != item and
            self.section == item.section and
            self.row == item.row and
            set(self.seats).issuperset(set(item.seats)))

    def seat_difference(self, item):
        return list(set(sorted(item.seats)).difference(set(sorted(self.seats))))
        
    def seat_difference_description(self, prev):
        self_seats = sorted(self.seats)
        prev_seats = sorted(prev.seats)
        diff_seats = self.seat_difference(prev)
        
        # if last item of diff_seats < first item of self_seats 
        # and last item of item_seats == last item of self_seats
        if ((diff_seats[-1] < self_seats[0]) and
            (prev_seats[-1] == self_seats[-1])):
            return 'top'
        
        # if first item of diff_seats > last item of self_seats
        # and first item of item_seats == first item of self_seats
        if ((diff_seats[0] > self_seats[-1]) and
            (prev_seats[0] == self_seats[0])):
            return 'bottom'
        
        # if first item of self_seats == first item of item_seats
        # and last item of self_seats == last item of item_seats
        # and first item of diff_seats != first item of item_seats
        # and last item of diff_seats != last item of item_seats
        if ((self_seats[0] == prev_seats[0]) and
            (self_seats[-1] == prev_seats[-1]) and
            (diff_seats[0] != prev_seats[0]) and
            (diff_seats[-1] != prev_seats[0])):
            return 'middle'
                
    def get_ticket_actions(self, prev):
        # if quantity increased, we must relist
        if len(self.seats) > len(prev.seats):
            d = {'action':'relist'}
            return self._replace(action = d, listing_id = prev.listing_id)
        # if seats aren't equal, we have a quantity change
        if self.seats != prev.seats:
            d = {}
            d['action'] = 'updatequantity'
            d['seats'] = prev.seats
            d['newseats'] = self.seats
            d['quantity'] = len(self.seats)
            d['removefrom'] = self.seat_difference_description(prev)
            return self._replace(action = d, listing_id = prev.listing_id)
        else:
            # seats match we must check if price changed
            if self.price != prev.price:
                return self._replace(action = {'action':'update'}, listing_id = prev.listing_id)
            else:
                return self

