#!/usr/bin/env python3
# Copyright (c) 2011, 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.
"""Module to manage IDL files."""

import copy
import pickle
import logging
import os
import os.path
import shutil
import idlnode
import idlrenderer
from generator import IsDartCollectionType, IsPureInterface

_logger = logging.getLogger('database')


class Database(object):
    """The Database class manages a collection of IDL files stored
  inside a directory.

  Each IDL is describing a single interface. The IDL files are written in the
  FremontCut syntax, which is derived from the Web IDL syntax and includes
  annotations.

  Database operations include adding, updating and removing IDL files.
  """

    def __init__(self, root_dir):
        """Initializes a Database over a given directory.

    Args:
      root_dir -- a directory. If directory does not exist, it will
      be created.
    """
        self._root_dir = root_dir
        if not os.path.exists(root_dir):
            _logger.debug('creating root directory %s' % root_dir)
            os.makedirs(root_dir)
        self._all_interfaces = {}
        self._interfaces_to_delete = []
        self._enums = {}
        self._all_dictionaries = {}
        # TODO(terry): Hack to remember all typedef unions.
        self._all_type_defs = {}

    def Clone(self):
        new_database = Database(self._root_dir)
        new_database._all_interfaces = copy.deepcopy(self._all_interfaces)
        new_database._interfaces_to_delete = copy.deepcopy(
            self._interfaces_to_delete)
        new_database._enums = copy.deepcopy(self._enums)
        new_database._all_dictionaries = copy.deepcopy(self._all_dictionaries)
        new_database._all_type_defs = copy.deepcopy(self._all_type_defs)

        return new_database

    def Delete(self):
        """Deletes the database by deleting its directory"""
        if os.path.exists(self._root_dir):
            shutil.rmtree(self._root_dir)
        # reset in-memory constructs
        self._all_interfaces = {}

    def _ScanForInterfaces(self):
        """Iterates over the database files and lists all interface names.

    Return:
      A list of interface names.
    """
        res = []

        def Visitor(_, dirname, names):
            for name in names:
                if os.path.isfile(os.path.join(dirname, name)):
                    root, ext = os.path.splitext(name)
                    if ext == '.idl':
                        res.append(root)

        os.path.walk(self._root_dir, Visitor, None)
        return res

    def _FilePath(self, interface_name):
        """Calculates the file path that a given interface should
    be saved to.

    Args:
      interface_name -- the name of the interface.
    """
        return os.path.join(self._root_dir, '%s.idl' % interface_name)

    def _LoadInterfaceFile(self, interface_name):
        """Loads an interface from the database.

    Returns:
      An IDLInterface instance or None if the interface is not found.
    Args:
      interface_name -- the name of the interface.
    """
        file_name = self._FilePath(interface_name)
        _logger.info('loading %s' % file_name)
        if not os.path.exists(file_name):
            return None

        f = open(file_name, 'r')
        content = f.read()
        f.close()

        # Parse file:
        idl_file = idlnode.IDLFile(self._idlparser.parse(content), file_name)

        if not idl_file.interfaces:
            raise RuntimeError('No interface found in %s' % file_name)
        elif len(idl_file.interfaces) > 1:
            raise RuntimeError('Expected one interface in %s' % file_name)

        interface = idl_file.interfaces[0]
        self._all_interfaces[interface_name] = interface
        return interface

    def Load(self):
        """Loads all interfaces into memory.
    """
        # FIXME: Speed this up by multi-threading.
        for (interface_name) in self._ScanForInterfaces():
            self._LoadInterfaceFile(interface_name)
        self.Cache()

    def Cache(self):
        """Serialize the database using pickle for faster startup in the future
    """
        output_file = open(os.path.join(self._root_dir, 'cache.pickle'), 'wb')
        pickle.dump(self._all_interfaces, output_file)
        pickle.dump(self._interfaces_to_delete, output_file)

    def LoadFromCache(self):
        """Deserialize the database using pickle for fast startup
    """
        input_file_name = os.path.join(self._root_dir, 'cache.pickle')
        if not os.path.isfile(input_file_name):
            self.Load()
            return
        input_file = open(input_file_name, 'rb')
        self._all_interfaces = pickle.load(input_file)
        self._interfaces_to_delete = pickle.load(input_file)
        input_file.close()

    def Save(self):
        """Saves all in-memory interfaces into files."""
        for interface in list(self._all_interfaces.values()):
            self._SaveInterfaceFile(interface)
        for interface_name in self._interfaces_to_delete:
            self._DeleteInterfaceFile(interface_name)

    def _SaveInterfaceFile(self, interface):
        """Saves an interface into the database.

    Args:
      interface -- an IDLInterface instance.
    """

        interface_name = interface.id

        # Actual saving
        file_path = self._FilePath(interface_name)
        _logger.debug('writing %s' % file_path)

        dir_name = os.path.dirname(file_path)
        if not os.path.exists(dir_name):
            _logger.debug('creating directory %s' % dir_name)
            os.mkdir(dir_name)

        # Render the IDLInterface object into text.
        text = idlrenderer.render(interface)

        f = open(file_path, 'w')
        f.write(text)
        f.close()

    def HasInterface(self, interface_name):
        """Returns True if the interface is in memory"""
        return interface_name in self._all_interfaces

    def GetInterface(self, interface_name):
        """Returns an IDLInterface corresponding to the interface_name
    from memory.

    Args:
      interface_name -- the name of the interface.
    """
        if interface_name not in self._all_interfaces:
            raise RuntimeError('Interface %s is not loaded' % interface_name)
        return self._all_interfaces[interface_name]

    def AddInterface(self, interface):
        """Returns an IDLInterface corresponding to the interface_name
    from memory.

    Args:
      interface -- the name of the interface.
    """
        interface_name = interface.id
        if interface_name in self._all_interfaces:
            raise RuntimeError('Interface %s already exists' % interface_name)
        self._all_interfaces[interface_name] = interface

    def GetInterfaces(self):
        """Returns a list of all loaded interfaces."""
        res = []
        for _, interface in sorted(self._all_interfaces.items()):
            res.append(interface)
        return res

    def DeleteInterface(self, interface_name):
        """Deletes an interface from the database. File is deleted when
    Save() is called.

    Args:
      interface_name -- the name of the interface.
    """
        if interface_name not in self._all_interfaces:
            raise RuntimeError('Interface %s not found' % interface_name)
        self._interfaces_to_delete.append(interface_name)
        del self._all_interfaces[interface_name]

    def _DeleteInterfaceFile(self, interface_name):
        """Actual file deletion"""
        file_path = self._FilePath(interface_name)
        if os.path.exists(file_path):
            _logger.debug('deleting %s' % file_path)
            os.remove(file_path)

    def Hierarchy(self, interface):
        yield interface
        for parent in interface.parents:
            parent_name = parent.type.id
            if not self.HasInterface(parent.type.id):
                continue
            for parent_interface in self.Hierarchy(
                    self.GetInterface(parent.type.id)):
                yield parent_interface

    def HasEnum(self, enum_name):
        return enum_name in self._enums

    def GetEnum(self, enum_name):
        return self._enums[enum_name]

    def AddEnum(self, enum):
        self._enums[enum.id] = enum

    def HasDictionary(self, dictionary_name):
        """Returns True if the dictionary is in memory"""
        return dictionary_name in self._all_dictionaries

    def GetDictionary(self, dictionary_name):
        """Returns an IDLDictionary corresponding to the dictionary_name
    from memory.

    Args:
      dictionary_name -- the name of the dictionary.
    """
        if dictionary_name not in self._all_dictionaries:
            raise RuntimeError('Dictionary %s is not loaded' % dictionary_name)
        return self._all_dictionaries[dictionary_name]

    def AddDictionary(self, dictionary):
        """Returns an IDLDictionary corresponding to the dictionary_name
    from memory.

    Args:
      dictionary -- the name of the dictionary.
    """
        dictionary_name = dictionary.id
        if dictionary_name in self._all_dictionaries:
            raise RuntimeError('Dictionary %s already exists' % dictionary_name)
        self._all_dictionaries[dictionary_name] = dictionary

    def GetDictionaries(self):
        """Returns a list of all loaded dictionaries."""
        res = []
        for _, dictionary in sorted(self._all_dictionaries.items()):
            res.append(dictionary)
        return res

    def HasTypeDef(self, type_def_name):
        """Returns True if the typedef is in memory"""
        return type_def_name in self._all_type_defs

    def GetTypeDef(self, type_def_name):
        """Returns an IDLTypeDef corresponding to the type_def_name
    from memory.

    Args:
      type_def_name -- the name of the typedef.
    """
        if type_def_name not in self._all_type_defs:
            raise RuntimeError('Typedef %s is not loaded' % type_def_name)
        return self._all_type_defs[type_def_name]

    def AddTypeDef(self, type_def):
        """Add only a typedef that a unions they map to any (no type)."""
        type_def_name = type_def.id
        if type_def_name in self._all_type_defs:
            raise RuntimeError('Typedef %s already exists' % type_def_name)
        self._all_type_defs[type_def_name] = type_def
        print('  Added typedef %s' % type_def_name)

    def TransitiveSecondaryParents(self, interface, propagate_event_target):
        """Returns a list of all non-primary parents.

    The list contains the interface objects for interfaces defined in the
    database, and the name for undefined interfaces.
    """

        def walk(parents, walk_result):
            for parent in parents:
                parent_name = parent.type.id
                if IsDartCollectionType(parent_name):
                    if not (parent_name in walk_result):
                        walk_result.append(parent_name)
                    continue
                if self.HasInterface(parent_name):
                    parent_interface = self.GetInterface(parent_name)
                    if not (parent_interface in walk_result):
                        # Interface has multi-inherited don't add interfaces more than once
                        # to our parent result list.
                        walk_result.append(parent_interface)
                    walk(parent_interface.parents, walk_result)
            return walk_result

        result = []
        if interface.parents:
            parent = interface.parents[0]
            if (IsPureInterface(parent.type.id, self) or
                (propagate_event_target and parent.type.id == 'EventTarget')):
                result = walk(interface.parents, [])
            else:
                result = walk(interface.parents[1:], [])

        return result
