# Copyright 2013, Big Switch Networks, Inc.
#
# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
# the following special exception:
#
# LOXI Exception
#
# As a special exception to the terms of the EPL, you may distribute libraries
# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
# that copyright and licensing notices generated by LoxiGen are not altered or removed
# from the LoxiGen Libraries and the notice provided below is (i) included in
# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
# documentation for the LoxiGen Libraries, if distributed in binary form.
#
# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
#
# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
# a copy of the EPL at:
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# EPL for the specific language governing permissions and limitations
# under the EPL.

"""
@brief Main Java Generation module
"""

import logging
import pdb
import os
import shutil

import loxi_globals
from loxi_ir import *
import lang_java
import test_data
from collections import namedtuple
from import_cleaner import ImportCleaner

import loxi_utils.loxi_utils as loxi_utils

import java_gen.java_model as java_model

logger = logging.getLogger(__name__)

def gen_all_java(install_dir):
    basedir= '%s/openflowj' % install_dir
    logger.info("Outputting to %s" % basedir)
    if os.path.exists(basedir):
        shutil.rmtree(basedir)
    os.makedirs(basedir)
    copy_prewrite_tree(basedir)
    gen = JavaGenerator(basedir, JavaGeneratorOptions(instrument=True))
    gen.create_of_interfaces()
    gen.create_of_classes()
    gen.create_of_const_enums()
    gen.create_of_factories()

JavaGeneratorOptions = namedtuple("JavaGeneratorOptions", ("instrument",))

class JavaGenerator(object):
    templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')

    def __init__(self, basedir, gen_opts):
        self.basedir = basedir
        self.java_model = java_model.model
        self.gen_opts = gen_opts

    def render_class(self, clazz, template, src_dir=None, **context):
        if not src_dir:
            src_dir = "src/main/java/"

        context['class_name'] = clazz.name
        context['package'] = clazz.package
        context['template_dir'] = self.templates_dir
        context['genopts']= self.gen_opts

        filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
        dirname = os.path.dirname(filename)
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        prefix = '//::(?=[ \t]|$)'
        print "filename: %s" % filename
        with open(filename, "w") as f:
            loxi_utils.render_template(f, template, [self.templates_dir], context, prefix=prefix)

        try:
            cleaner = ImportCleaner(filename)
            cleaner.find_used_imports()
            cleaner.rewrite_file(filename)
        except:
            print 'Cannot clean imports from file %s' % filename

    def create_of_const_enums(self):
        for enum in self.java_model.enums:
            if enum.name in ["OFPort"]:
                continue
            self.render_class(clazz=enum,
                    template='const.java', enum=enum, all_versions=self.java_model.versions)

            for version in enum.versions:
                clazz = java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol.ver{}".format(version.of_version), name="{}SerializerVer{}".format(enum.name, version.of_version))

                if enum.is_bitmask:
                    self.render_class(clazz=clazz, template="const_set_serializer.java", enum=enum, version=version)
                else:
                    self.render_class(clazz=clazz, template="const_serializer.java", enum=enum, version=version)

    def create_of_interfaces(self):
        """ Create the base interfaces for of classes"""
        for interface in self.java_model.interfaces:
            #if not utils.class_is_message(interface.c_name):
            #    continue
            self.render_class(clazz=interface,
                    template="of_interface.java", msg=interface)

    def create_of_classes(self):
        """ Create the OF classes with implementations for each of the interfaces and versions """
        for interface in self.java_model.interfaces:
            for java_class in interface.versioned_classes:
                if self.java_model.generate_class(java_class):
                    if not java_class.is_virtual:
                        self.render_class(clazz=java_class,
                                template='of_class.java', version=java_class.version, msg=java_class,
                                impl_class=java_class.name)

                        self.create_unit_test(java_class.unit_test)
                    else:
                        disc = java_class.discriminator
                        if disc:
                            self.render_class(clazz=java_class,
                                template='of_virtual_class.java', version=java_class.version, msg=java_class,
                                impl_class=java_class.name, model=self.java_model)
                        else:
                            print "Class %s virtual but no discriminator" % java_class.name
                else:
                    print "Class %s ignored by generate_class" % java_class.name

    def create_unit_test(self, unit_tests):
        if unit_tests.has_test_data:
            for i in range(unit_tests.length):
                unit_test = unit_tests.get_test_unit(i)
                if unit_test.has_test_data:
                    self.render_class(clazz=unit_test,
                            template='unit_test.java', src_dir="src/test/java",
                            version=unit_test.java_class.version,
                            test=unit_test, msg=unit_test.java_class,
                            test_data=unit_test.test_data)

    def create_of_factories(self):
        for factory in self.java_model.of_factories:
            self.render_class(clazz=factory, template="of_factory_interface.java", factory=factory)
            for factory_class in factory.factory_classes:
                self.render_class(clazz=factory_class, template="of_factory_class.java", factory=factory_class, model=self.java_model)
            self.render_class(clazz=java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol", name="OFFactories"), template="of_factories.java", versions=self.java_model.versions)

def copy_prewrite_tree(basedir):
    """ Recursively copy the directory structure from ./java_gen/pre-write
       into $basedir"""
    print "Copying pre-written files into %s" % basedir
