# Path: laice/utils/spacy_ner.py
# def train_query(queryObj):
# def get_query(queryObj):
# def clean_story(story):
# def retrain_story(story):
#     ENTITY_OFFSETS = []
#     ENTITY_LIST = []
#     TRAIN_DATA = [
#         (
#             querystring,
#             ENTITY_OFFSETS
#         ),
#     ]
#     ENTITY_LIST = []
# 
# Path: laice/core/viewsets.py
# class ViewMappingMixin:
#     list_methods = ['list', 'create']
#     detail_methods = ['retrieve', 'destroy']
# 
#     protocol_mapping = {
#         'create': 'post',
#         'retrieve': 'get',
#         'list': 'get',
#         'partial_update': 'patch',
#         'update': 'patch',
#         'destroy': 'delete'
#     }
# 
#     @classmethod
#     def list_mapping(cls):
#         return cls.as_view(dict((cls.protocol_mapping[key], key) for key in cls.list_methods))
# 
#     @classmethod
#     def detail_mapping(cls):
#         return cls.as_view(dict((cls.protocol_mapping[key], key) for key in cls.detail_methods))
# 
# Path: stories/models.py
# class Story(models.Model):
#     name = models.CharField(
#         max_length=128,
#         unique=True,
#     )
# 
#     training = models.BooleanField(default=False)
# 
#     @property
#     def unconfigured_requests(self):
#         return self.query_set.filter(configured=False).count()
# 
#     def perform_clean(self):
#         if self.name:
#             # Replace whitespaces
#             self.name = self.name.replace(' ', '')
# 
#             # Replace special characters with '-'
#             self.name = map(lambda x: x if (x.isalnum() or x == '-') else '-', self.name)
#             self.name = ''.join(self.name)
# 
#     def save(self, *args, **kwargs):
#         self.perform_clean()
#         super().save(*args, **kwargs)
# 
#     def __str__(self):
#         return self.name
# 
# class Query(models.Model):
#     # Querystring
#     querystring = models.TextField()
# 
#     # Each query will belong to a story
#     story = models.ForeignKey(Story, null=False)
# 
#     # Has the querystring been configured
#     # by configured I mean manually parsed
#     configured = models.BooleanField(default=False)
# 
#     # Store it's named entity recognizier via Spacy
#     parsed_ner = JSONField(blank=True, null=True)
# 
#     def __str__(self):
#         return self.querystring + ' | ' + str(self.story)
# 
# Path: stories/serializers.py
# class StorySerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Story
#         fields = ('name', 'training', 'unconfigured_requests')
# 
# class StoryAttributeSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = StoryAttribute
#         fields = ('attribute',)
# 
# class InputStoryAttributeSerializer(serializers.ModelSerializer):
#     story = serializers.SlugRelatedField(
#         slug_field='name',
#         queryset=Story.objects.all()
#     )
# 
#     class Meta:
#         model = StoryAttribute
# 
# class QuerySerializer(serializers.ModelSerializer):
#     parsed_ner = serializers.DictField()
# 
#     class Meta:
#         model = Query
#         fields = ('id', 'querystring', 'configured', 'parsed_ner')
# 
# class InputQuerySerializer(serializers.ModelSerializer):
#     story = serializers.SlugRelatedField(
#         slug_field='name',
#         queryset=Story.objects.all()
#     )
# 
#     class Meta:
#         model = Query
#         fields = ('id', 'querystring', 'story')
# 
# class QueryNERSerializer(serializers.Serializer):
#     ner = serializers.DictField()
# 
#     class Meta:
#         fields = ('parsed_ner',)
# 
# Path: stories/viewsets.py
# class GetStoryMixin:
#     first_key = 'story_name'
# 
#     def get_object(self):
#         try:
#             story = self.queryset.get(name=self.kwargs[self.first_key])
#         except (ObjectDoesNotExist):
#             raise exceptions.NotFound()
#         return story


from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets, exceptions, status
from rest_framework.response import Response
from laice.utils import spacy_ner
from laice.core.viewsets import ViewMappingMixin
from stories.models import Story, Query
from stories.serializers import (
    StorySerializer,
    StoryAttributeSerializer,
    InputStoryAttributeSerializer,
    QuerySerializer,
    InputQuerySerializer,
    QueryNERSerializer
)
from stories.viewsets import GetStoryMixin
import threading, time
# Rest framework ViewSets
# Story
class StoryViewSet(GetStoryMixin, ViewMappingMixin, viewsets.ModelViewSet):
    queryset = Story.objects.all()
    serializer_class = StorySerializer

    def list(self, request, *args, **kwargs):
        serializer = self.get_serializer(Story.objects.all(), many=True)
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        story = self.get_object()
        story.delete()
        spacy_ner.clean_story(story)
        return Response(status=status.HTTP_204_NO_CONTENT)


# Story retrain
class StoryRetrainViewSet(GetStoryMixin, ViewMappingMixin, viewsets.ModelViewSet):
    list_methods = ['create', 'list']

    queryset = Story.objects.all()
    serializer_class = StorySerializer

    # Retrain data at this point
    def create(self, request, *args, **kwargs):
        # Start retraining thread
        story = self.get_object()
        story.training = True
        story.save()

# Path: laice/utils/spacy_ner.py
# def train_query(queryObj):
# def get_query(queryObj):
# def clean_story(story):
# def retrain_story(story):
#     ENTITY_OFFSETS = []
#     ENTITY_LIST = []
#     TRAIN_DATA = [
#         (
#             querystring,
#             ENTITY_OFFSETS
#         ),
#     ]
#     ENTITY_LIST = []
# 
# Path: laice/core/viewsets.py
# class ViewMappingMixin:
#     list_methods = ['list', 'create']
#     detail_methods = ['retrieve', 'destroy']
# 
#     protocol_mapping = {
#         'create': 'post',
#         'retrieve': 'get',
#         'list': 'get',
#         'partial_update': 'patch',
#         'update': 'patch',
#         'destroy': 'delete'
#     }
# 
#     @classmethod
#     def list_mapping(cls):
#         return cls.as_view(dict((cls.protocol_mapping[key], key) for key in cls.list_methods))
# 
#     @classmethod
#     def detail_mapping(cls):
#         return cls.as_view(dict((cls.protocol_mapping[key], key) for key in cls.detail_methods))
# 
# Path: stories/models.py
# class Story(models.Model):
#     name = models.CharField(
#         max_length=128,
#         unique=True,
#     )
# 
#     training = models.BooleanField(default=False)
# 
#     @property
#     def unconfigured_requests(self):
#         return self.query_set.filter(configured=False).count()
# 
#     def perform_clean(self):
#         if self.name:
#             # Replace whitespaces
#             self.name = self.name.replace(' ', '')
# 
#             # Replace special characters with '-'
#             self.name = map(lambda x: x if (x.isalnum() or x == '-') else '-', self.name)
#             self.name = ''.join(self.name)
# 
#     def save(self, *args, **kwargs):
#         self.perform_clean()
#         super().save(*args, **kwargs)
# 
#     def __str__(self):
#         return self.name
# 
# class Query(models.Model):
#     # Querystring
#     querystring = models.TextField()
# 
#     # Each query will belong to a story
#     story = models.ForeignKey(Story, null=False)
# 
#     # Has the querystring been configured
#     # by configured I mean manually parsed
#     configured = models.BooleanField(default=False)
# 
#     # Store it's named entity recognizier via Spacy
#     parsed_ner = JSONField(blank=True, null=True)
# 
#     def __str__(self):
#         return self.querystring + ' | ' + str(self.story)
# 
# Path: stories/serializers.py
# class StorySerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Story
#         fields = ('name', 'training', 'unconfigured_requests')
# 
# class StoryAttributeSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = StoryAttribute
#         fields = ('attribute',)
# 
# class InputStoryAttributeSerializer(serializers.ModelSerializer):
#     story = serializers.SlugRelatedField(
#         slug_field='name',
#         queryset=Story.objects.all()
#     )
# 
#     class Meta:
#         model = StoryAttribute
# 
# class QuerySerializer(serializers.ModelSerializer):
#     parsed_ner = serializers.DictField()
# 
#     class Meta:
#         model = Query
#         fields = ('id', 'querystring', 'configured', 'parsed_ner')
# 
# class InputQuerySerializer(serializers.ModelSerializer):
#     story = serializers.SlugRelatedField(
#         slug_field='name',
#         queryset=Story.objects.all()
#     )
# 
#     class Meta:
#         model = Query
#         fields = ('id', 'querystring', 'story')
# 
# class QueryNERSerializer(serializers.Serializer):
#     ner = serializers.DictField()
# 
#     class Meta:
#         fields = ('parsed_ner',)
# 
# Path: stories/viewsets.py
# class GetStoryMixin:
#     first_key = 'story_name'
# 
#     def get_object(self):
#         try:
#             story = self.queryset.get(name=self.kwargs[self.first_key])
#         except (ObjectDoesNotExist):
#             raise exceptions.NotFound()
#         return story


# Path: stories/views.py
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets, exceptions, status
from rest_framework.response import Response
from laice.utils import spacy_ner
from laice.core.viewsets import ViewMappingMixin
from stories.models import Story, Query
from stories.serializers import (
    StorySerializer,
    StoryAttributeSerializer,
    InputStoryAttributeSerializer,
    QuerySerializer,
    InputQuerySerializer,
    QueryNERSerializer
)
from stories.viewsets import GetStoryMixin
import threading, time

# Rest framework ViewSets
# Story
class StoryViewSet(GetStoryMixin, ViewMappingMixin, viewsets.ModelViewSet):
    queryset = Story.objects.all()
    serializer_class = StorySerializer

    def list(self, request, *args, **kwargs):
        serializer = self.get_serializer(Story.objects.all(), many=True)
        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        story = self.get_object()
        story.delete()
        spacy_ner.clean_story(story)
        return Response(status=status.HTTP_204_NO_CONTENT)


# Story retrain
class StoryRetrainViewSet(GetStoryMixin, ViewMappingMixin, viewsets.ModelViewSet):
    list_methods = ['create', 'list']

    queryset = Story.objects.all()
    serializer_class = StorySerializer

    # Retrain data at this point
    def create(self, request, *args, **kwargs):
        # Start retraining thread
        story = self.get_object()
        story.training = True
        story.save()

        threading.Thread(target=spacy_ner.retrain_story(story)).start()