import re
import csv

from django.db import models
from passerelle.base.models import BaseResource

class BaseDataSource(BaseResource):

    def get_data(self, **kwargs):
        raise NotImplementedError

    def get_data_by_id(self, id,  **kwargs):
        for row in self.get_data(**kwargs):
            if row.get('id') == id:
                return row.get('text')
        return None

    def post_data(self, **kwargs):
        raise NotImplementedError

    def post_data_by_id(self, id, **kwargs):
        raise NotImplementedError


class CsvDataSource(BaseDataSource):
    csv_file = models.FileField(upload_to='csv')
    key_column = models.IntegerField()
    value_columns = models.CommaSeparatedIntegerField(max_length=100)

    parameters = ('columns', 'filter')

    def get_data(self, columns=None, filter=None):
        data = []
        self.csv_file.open()
        dialect = csv.Sniffer().sniff(self.csv_file.read(1024))
        self.csv_file.seek(0)
        reader = csv.reader(self.csv_file, dialect)

        def get_value(row, columns):
            return (' '.join([unicode(row[int(x)-1], 'utf-8') for x in columns]))

        def get_key(row):
            if self.key_column:
                return unicode(row[self.key_column-1], 'utf-8')
            else:
                return get_value(row).lower().encode('ascii', 'ignore').replace(' ', '-')

        def filter_row(row, column, op, value):
            if op == '==':
                return value == unicode(row[filter['column']-1], 'utf-8')
            if op == '!=':
                return value != unicode(row[filter['column']-1], 'utf-8')
            raise NotImplementedError('invalid operator in filter')

        if columns:
            columns = columns.split(',')
        else:
            columns = self.value_columns.split(',')

        if filter:
            filter = re.match('^(?P<column>\d+)(?P<op>==|!=)(?P<value>.*)$', filter)
            if filter is None:
                raise ValueError('invalid filter')
            filter = filter.groupdict()
            filter['column'] = int(filter['column'])

        for row in reader:
            if filter and not filter_row(row, **filter):
                continue
            data.append({'id': get_key(row), 'text': get_value(row, columns)})

        data.sort(lambda x,y: cmp(x['text'], y['text']))
        return data
