# -*- coding: utf-8 -*-
from datetime import datetime
import json
import logging
import os
import shutil
import unicodedata

from sqlalchemy.orm import load_only
import ox
import sqlalchemy as sa

from changelog import add_record
from db import MutableDict
import db
import json_pickler
import settings
import state
import utils
import media
from websocket import trigger_event


logger = logging.getLogger(__name__)


class Annotation(db.Model):
    __tablename__ = 'annotation'

    _id = sa.Column(sa.Integer(), primary_key=True)
    id = sa.Column(sa.String(43))
    created = sa.Column(sa.DateTime())
    modified = sa.Column(sa.DateTime())

    user_id = sa.Column(sa.String(43), sa.ForeignKey('user.id'))
    user = sa.orm.relationship('User', backref=sa.orm.backref('annotations', lazy='dynamic'))
    item_id = sa.Column(sa.String(43), sa.ForeignKey('item.id'))
    item = sa.orm.relationship('Item', backref=sa.orm.backref('items', lazy='dynamic'))
    data = sa.Column(MutableDict.as_mutable(sa.PickleType(pickler=json_pickler)))

    findquotes = sa.Column(sa.Text(), index=True)
    findnotes = sa.Column(sa.Text(), index=True)

    def __init__(self, item_id, user_id, data):
        self.created = datetime.utcnow()
        self.modified = datetime.utcnow()
        self.item_id = item_id
        self.user_id = user_id
        self.data = data

    @classmethod
    def create(cls, item_id, user_id, data):
        a = cls(item_id, user_id, data)
        a.save()
        return a

    def delete(self):
        state.db.session.delete(self)
        state.db.session.commit()

    @classmethod
    def get(cls, user, item_id, annotation_id):
        if isinstance(user, str):
            qs = cls.query.filter_by(item_id=item_id, user_id=user, id=annotation_id)
        else:
            qs = cls.query.filter_by(item_id=item_id, user=user, id=annotation_id)
        for a in qs:
            return a

    @classmethod
    def get_by_item(cls, item_id):
        annotations = []
        for a in cls.query.filter_by(item_id=item_id):
            annotations.append(a.json())
        return annotations

    def save(self):
        id = self.data.get('id')
        if id:
            self.id = id
        self.findquotes = unicodedata.normalize('NFKD', self.data.get('text', '')).lower()
        note = self.data.get('notes', {})
        if isinstance(note, list) and note:
            note = note[0]
        if isinstance(note, dict):
            note = note.get('value', '')
        else:
            note = ''
        self.findnotes = unicodedata.normalize('NFKD', note).lower()
        state.db.session.add(self)
        state.db.session.commit()

    def json(self):
        data = self.data.copy()
        data['created'] = self.created
        data['modified'] = self.modified
        data['user'] = self.user_id
        data['_id'] = ox.toAZ(self._id)
        if isinstance(data.get('notes'), dict):
            note = data['notes']
            if self.user_id != settings.USER_ID:
                note['user'] = self.user_id
                if not note.get('id'):
                    note['id'] = 'A'
            data['notes'] = [data['notes']]
        if 'notes' not in data:
            data['notes'] = []
        return data

    def add_record(self, action):
        args = [self.item_id]
        if action == 'addannotation':
            args.append(self.data)
        elif action == 'editannotation':
            args.append(self.id)
            args.append({
                'notes': self.data['notes']
            })
        elif action == 'removeannotation':
            args.append(self.id)
        else:
            raise Exception('unknown action')
        add_record(action, *args)