import ast
import autopep8
import inspect
from django.core.management import BaseCommand
from django.db import models
from armada_sde import models as sde, __version__ as sde_version
from armada_sde_rest import __version__ as version



QUERYSET_OVERRIDE = {
    'InvType': 'filter(published=True)'
}

VIEWSETS_HEADER = '''# Generated by v{} for sde v{}
from armada_sde import models
from . import serializers
from .viewsets import SDEViewSet
'''.format(version, sde_version)
SERIALIZERS_HEADER = '''# Generated by  v{} for sde v{}
from rest_framework import serializers
from armada_sde import models
'''.format(version, sde_version)

URLS_HEADER = '''# Generated by v{} for sde v{}
from rest_framework.routers import DefaultRouter
from . import views


router = DefaultRouter() 
'''.format(version, sde_version)

URLS_FOOTER = '''urlpatterns = router.urls'''


class Command(BaseCommand):
    help = ('Generates viewsets and serializers for SDE models.')
    requires_model_validation = False
    requires_system_checks = False

    def add_arguments(self, parser):
        parser.add_argument('-s', '--serializers', action='store',
                            dest='serializers', default='-',
                            help='Write serializers to this file')
        parser.add_argument('-i', '--viewsets', action='store',
                            dest='viewsets', default='-',
                            help='Write viewsets to this file')
        parser.add_argument('-u', '--urls', action='store',
                            dest='urls', default='-',
                            help='Write urls to this file')

    def handle(self, *args, **options):
        viewset_filename = options['viewsets']
        viewset_lines = VIEWSETS_HEADER.splitlines()
        serializer_filename = options['serializers']
        serializer_lines = SERIALIZERS_HEADER.splitlines()
        urls_filename = options['urls']
        urls_lines = URLS_HEADER.splitlines()

        for name in dir(sde):
            sde_class = getattr(sde, name)
            if inspect.isclass(sde_class) and issubclass(sde_class,
                                                         models.Model):
                for line in self.generate_viewset(name):
                    viewset_lines.append(line)

                for line in self.generate_serializer(sde_class, name):
                    serializer_lines.append(line)

                for line in self.generate_urls(name):
                    urls_lines.append(line)

        viewset_code = autopep8.fix_code('\n'.join(viewset_lines))
        try:
            ast.parse(viewset_code)
            if viewset_filename == '-':
                self.stdout.write(viewset_code)
            else:
                with open(viewset_filename, 'w') as output_file:
                    output_file.write(viewset_code)
                    output_file.write('\n')

            self.stdout.write('\nSDE viewsets generated\n')
        except SyntaxError as ex:
            self.stderr.write('Could not parse generated viewsets file\n')
            raise ex

        serializer_code = autopep8.fix_code('\n'.join(serializer_lines))
        try:
            ast.parse(serializer_code)
            if serializer_filename == '-':
                self.stdout.write(serializer_code)
            else:
                with open(serializer_filename, 'w') as output_file:
                    output_file.write('\n\n')
                    output_file.write(serializer_code)
                    output_file.write('\n')

            self.stdout.write('\nSDE serializers generated\n')
        except SyntaxError as ex:
            self.stderr.write('Could not parse generated serializers file\n')
            raise ex

        urls_lines.extend(URLS_FOOTER.splitlines())
        urls_code = autopep8.fix_code('\n'.join(urls_lines))
        try:
            ast.parse(urls_code)
            if urls_filename == '-':
                self.stdout.write(urls_code)
            else:
                with open(urls_filename, 'w') as output_file:
                    output_file.write(urls_code)
                    output_file.write('\n')

            self.stdout.write('\nSDE urls generated\n')
        except SyntaxError as ex:
            self.stderr.write('Could not parse generated urls file\n')
            raise ex

    def generate_viewset(self, name):
        yield ''
        yield ''
        yield 'class {}ViewSet(SDEViewSet):'.format(name)
        yield '    list_serializer = serializers.{}ListSerializer'.format(name)
        yield '    details_serializer = serializers.{}DetailsSerializer'.format(
            name
        )
        if name in QUERYSET_OVERRIDE:
            yield '    queryset = models.{}.objects.{}'.format(
                name,
                QUERYSET_OVERRIDE[name])
        else:
            yield '    queryset = models.{}.objects.all()'.format(name)

    def generate_serializer(self, sde_class, name):
        yield ''
        yield ''
        yield 'class {}ListSerializer(serializers.ModelSerializer):'.format(
            name)
        yield '    class Meta(object):'
        yield '        model = models.{}'.format(name)
        if sde_class.get_name_field():
            yield '        fields = {}'.format((sde_class.get_pk_field(),
                                          sde_class.get_name_field()))
        else:
            yield '        fields= (\'{}\', )'.format(sde_class.get_pk_field())
        yield ''
        yield ''
        yield 'class {}DetailsSerializer(serializers.ModelSerializer):'.format(
            name)
        yield '    class Meta(object):'
        yield '        model = models.{}'.format(name)
        yield '        fields = \'__all__\''

    def generate_urls(self, name):
        yield 'router.register(r\'{}\','.format(name.lower())
        yield '                views.{}ViewSet,'.format(name)
        yield '                base_name=\'armada_sde_{}\')'.format(
            name.lower())
