#!/usr/bin/env python3
# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""Tests for dartgenerator."""

import logging.config
import os.path
import re
import shutil
import tempfile
import unittest
import dartgenerator
import database
import idlnode
import idlparser


class DartGeneratorTestCase(unittest.TestCase):

    def _InDatabase(self, interface_name):
        return os.path.exists(
            os.path.join(self._database_dir, '%s.idl' % interface_name))

    def _FilePathForDartInterface(self, interface_name):
        return os.path.join(self._generator._output_dir, 'src', 'interface',
                            '%s.dart' % interface_name)

    def _InOutput(self, interface_name):
        return os.path.exists(self._FilePathForDartInterface(interface_name))

    def _ReadOutputFile(self, interface_name):
        self.assertTrue(self._InOutput(interface_name))
        file_path = self._FilePathForDartInterface(interface_name)
        f = open(file_path, 'r')
        content = f.read()
        f.close()
        return content, file_path

    def _AssertOutputSansHeaderEquals(self, interface_name, expected_content):
        full_actual_content, file_path = self._ReadOutputFile(interface_name)
        # Remove file header comments in // or multiline /* ... */ syntax.
        header_re = re.compile(r'^(\s*(//.*|/\*([^*]|\*[^/])*\*/)\s*)*')
        actual_content = header_re.sub('', full_actual_content)
        if expected_content != actual_content:
            msg = """
FILE: %s
EXPECTED:
%s
ACTUAL:
%s
""" % (file_path, expected_content, actual_content)
            self.fail(msg)

    def _AssertOutputContains(self, interface_name, expected_content):
        actual_content, file_path = self._ReadOutputFile(interface_name)
        if expected_content not in actual_content:
            msg = """
STRING: %s
Was found not in output file: %s
FILE CONTENT:
%s
""" % (expected_content, file_path, actual_content)
            self.fail(msg)

    def _AssertOutputDoesNotContain(self, interface_name, expected_content):
        actual_content, file_path = self._ReadOutputFile(interface_name)
        if expected_content in actual_content:
            msg = """
STRING: %s
Was found in output file: %s
FILE CONTENT:
%s
""" % (expected_content, file_path, actual_content)
            self.fail(msg)

    def setUp(self):
        self._working_dir = tempfile.mkdtemp()
        self._output_dir = os.path.join(self._working_dir, 'output')
        self._database_dir = os.path.join(self._working_dir, 'database')
        self._auxiliary_dir = os.path.join(self._working_dir, 'auxiliary')
        self.assertFalse(os.path.exists(self._database_dir))

        # Create database and add one interface.
        db = database.Database(self._database_dir)
        os.mkdir(self._auxiliary_dir)
        self.assertTrue(os.path.exists(self._database_dir))

        content = """
    module shapes {
      @A1 @A2
      interface Shape {
        @A1 @A2 getter attribute int attr;
        @A1 setter attribute int attr;
        @A3 boolean op();
        const long CONSTANT = 1;
        getter attribute DOMString strAttr;
        Shape create();
        boolean compare(Shape s);
        Rectangle createRectangle();
        void addLine(lines::Line line);
        void someDartType(File file);
        void someUnidentifiedType(UnidentifiableType t);
      };
    };

    module rectangles {
      @A3
      interface Rectangle : @A3 shapes::Shape {
        void someTemplatedType(List<Shape> list);
      };
    };

    module lines {
      @A1
      interface Line : shapes::Shape {
      };
    };
    """

        parser = idlparser.IDLParser(idlparser.FREMONTCUT_SYNTAX)
        ast = parser.parse(content)
        idl_file = idlnode.IDLFile(ast)
        for interface in idl_file.interfaces:
            db.AddInterface(interface)
        db.Save()

        self.assertTrue(self._InDatabase('Shape'))
        self.assertTrue(self._InDatabase('Rectangle'))
        self.assertTrue(self._InDatabase('Line'))

        self._database = database.Database(self._database_dir)
        self._generator = dartgenerator.DartGenerator(self._auxiliary_dir,
                                                      '../templates', 'test')

    def tearDown(self):
        shutil.rmtree(self._database_dir)
        shutil.rmtree(self._auxiliary_dir)

    def testBasicGeneration(self):
        # Generate all interfaces:
        self._database.Load()
        self._generator.Generate(self._database, self._output_dir)
        self._generator.Flush()

        self.assertTrue(self._InOutput('Shape'))
        self.assertTrue(self._InOutput('Rectangle'))
        self.assertTrue(self._InOutput('Line'))

    def testFilterByAnnotations(self):
        self._database.Load()
        self._generator.FilterInterfaces(self._database, ['A1', 'A2'], ['A3'])
        self._generator.Generate(self._database, self._output_dir)
        self._generator.Flush()

        # Only interfaces with (@A1 and @A2) or @A3 should be generated:
        self.assertTrue(self._InOutput('Shape'))
        self.assertTrue(self._InOutput('Rectangle'))
        self.assertFalse(self._InOutput('Line'))

        # Only members with (@A1 and @A2) or @A3 should be generated:
        # TODO(sra): make th
        self._AssertOutputSansHeaderEquals(
            'Shape', """interface Shape {

  final int attr;

  bool op();
}
""")

        self._AssertOutputContains('Rectangle',
                                   'interface Rectangle extends shapes::Shape')

    def testTypeRenames(self):
        self._database.Load()
        # Translate 'Shape' to spanish:
        self._generator.RenameTypes(self._database, {'Shape': 'Forma'}, False)
        self._generator.Generate(self._database, self._output_dir)
        self._generator.Flush()

        # Validate that all references to Shape have been converted:
        self._AssertOutputContains('Forma', 'interface Forma')
        self._AssertOutputContains('Forma', 'Forma create();')
        self._AssertOutputContains('Forma', 'bool compare(Forma s);')
        self._AssertOutputContains('Rectangle',
                                   'interface Rectangle extends Forma')

    def testQualifiedDartTypes(self):
        self._database.Load()
        self._generator.FilterMembersWithUnidentifiedTypes(self._database)
        self._generator.Generate(self._database, self._output_dir)
        self._generator.Flush()

        # Verify primitive conversions are working:
        self._AssertOutputContains('Shape', 'static const int CONSTANT = 1')
        self._AssertOutputContains('Shape', 'final String strAttr;')

        # Verify interface names are converted:
        self._AssertOutputContains('Shape', 'interface Shape {')
        self._AssertOutputContains('Shape', ' Shape create();')
        # TODO(sra): Why is this broken? Output contains qualified type.
        #self._AssertOutputContains('Shape',
        #                           'void addLine(Line line);')
        self._AssertOutputContains('Shape', 'Rectangle createRectangle();')
        # TODO(sra): Why is this broken? Output contains qualified type.
        #self._AssertOutputContains('Rectangle',
        #                           'interface Rectangle extends Shape')
        # Verify dart names are preserved:
        # TODO(vsm): Re-enable when package / namespaces are enabled.
        # self._AssertOutputContains('shapes', 'Shape',
        #   'void someDartType(File file);')

        # Verify that unidentified types are not removed:
        self._AssertOutputDoesNotContain('Shape', 'someUnidentifiedType')

        # Verify template conversion:
        # TODO(vsm): Re-enable when core collections are supported.
        # self._AssertOutputContains('rectangles', 'Rectangle',
        #  'void someTemplatedType(List<Shape> list)')


if __name__ == '__main__':
    logging.config.fileConfig('logging.conf')
    if __name__ == '__main__':
        unittest.main()
