#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
'''IDL Node defines the IDLAttribute and IDLNode objects which are constructed
by the parser as it processes the various 'productions'.'''
# pylint: disable=unidiomatic-typecheck
import sys

#
# IDL Node
#
# IDL Node defines the IDLAttribute and IDLNode objects which are constructed
# by the parser as it processes the various 'productions'.  The IDLAttribute
# objects are assigned to the IDLNode's property dictionary instead of being
# applied as children of The IDLNodes, so they do not exist in the final tree.
# The AST of IDLNodes is the output from the parsing state and will be used
# as the source data by the various generators.
#


#
# CopyToList
#
# Takes an input item, list, or None, and returns a new list of that set.
def CopyToList(item):
  # If the item is 'Empty' make it an empty list
  if not item:
    item = []

  # If the item is not a list
  if type(item) is not type([]):
    item = [item]

  # Make a copy we can modify
  return list(item)


# IDLSearch
#
# A temporary object used by the parsing process to hold an Extended Attribute
# which will be passed as a child to a standard IDLNode.
#
class IDLSearch(object):

  def __init__(self):
    self.depth = 0

  def Enter(self, node):
    pass

  def Exit(self, node):
    pass


# IDLAttribute
#
# A temporary object used by the parsing process to hold an Extended Attribute
# which will be passed as a child to a standard IDLNode.
#
class IDLAttribute(object):
  '''A temporary object used by the parsing process to hold an Extended
  Attribute which will be passed as a child to a standard IDLNode.'''

  def __init__(self, name, value):
    self._cls = 'Property'
    self.name = name
    self.value = value

  def __str__(self):
    return f'{self.name}={self.value}'

  def GetClass(self):
    return self._cls


#
# IDLNode
#
# This class implements the AST tree, providing the associations between
# parents and children.  It also contains a namespace and propertynode to
# allow for look-ups.  IDLNode is derived from IDLRelease, so it is
# version aware.
#
class IDLNode(object):
  '''This class implements the AST tree, providing the associations between
  parents and children.  It also contains a namespace and propertynode to
  allow for look-ups.  IDLNode is derived from IDLRelease, so it is
  version aware.'''

  def __init__(self, cls, filename, lineno, pos, children=None):
    self._cls = cls
    self._properties = {
        'ERRORS': [],
        'WARNINGS': [],
        'FILENAME': filename,
        'LINENO': lineno,
        'POSSITION': pos,
    }

    self._children = []
    self._parent = None
    self.AddChildren(children)

#
#
#
# Return a string representation of this node

  def __str__(self):
    name = self.GetProperty('NAME', '')
    return f'{self._cls}({name})'

  def GetLogLine(self, msg):
    filename, lineno = self.GetFileAndLine()
    return f'{filename}({lineno}) : {msg}\n'

  # Log an error for this object
  def Error(self, msg):
    self.GetProperty('ERRORS').append(msg)
    sys.stderr.write(self.GetLogLine('error: ' + msg))

  # Log a warning for this object
  def Warning(self, msg):
    self.GetProperty('WARNINGS').append(msg)
    sys.stdout.write(self.GetLogLine('warning:' + msg))

  # Return file and line number for where node was defined
  def GetFileAndLine(self):
    return self.GetProperty('FILENAME'), self.GetProperty('LINENO')

  def GetClass(self):
    return self._cls

  def GetName(self):
    return self.GetProperty('NAME')

  def GetParent(self):
    return self._parent

  def Traverse(self, search, filter_nodes):
    if self._cls in filter_nodes:
      return ''

    search.Enter(self)
    search.depth += 1
    for child in self._children:
      child.Traverse(search, filter_nodes)
    search.depth -= 1
    search.Exit(self)

  def Tree(self, filter_nodes=None, accept_props=None):

    class DumpTreeSearch(IDLSearch):
      '''Class implementing DumpTreeSearch'''

      def __init__(self, props):
        IDLSearch.__init__(self)
        self.out = []
        self.props = props

      def Enter(self, node):
        tab = ''.rjust(self.depth * 2)
        self.out.append(tab + str(node))
        if self.props:
          proplist = []
          for key, value in node.GetProperties().iteritems():
            if key in self.props:
              proplist.append(tab + f'    {key}: {str(value)}')
          if proplist:
            self.out.append(tab + '  PROPERTIES')
            self.out.extend(proplist)

    if filter_nodes is None:
      filter_nodes = ['Comment', 'Copyright']

    search = DumpTreeSearch(accept_props)
    self.Traverse(search, filter_nodes)
    return search.out

#
# Search related functions
#
# Check if node is of a given type

  def IsA(self, *typelist):
    if self._cls in typelist:
      return True
    return False

  # Get a list of all children
  def GetChildren(self):
    return self._children

  def GetListOf(self, *keys):
    out = []
    for child in self.GetChildren():
      if child.GetClass() in keys:
        out.append(child)
    return out

  def GetOneOf(self, *keys):
    out = self.GetListOf(*keys)
    if out:
      return out[0]
    return None

  def AddChildren(self, children):
    children = CopyToList(children)
    for child in children:
      if not child:
        continue
      if type(child) == IDLAttribute:
        self.SetProperty(child.name, child.value)
        continue
      if type(child) == IDLNode:
        child._parent = self  # pylint: disable=protected-access
        self._children.append(child)
        continue
      raise RuntimeError(f'Adding child of type {type(child).__name__}.\n')


#
# Property Functions
#

  def SetProperty(self, name, val):
    self._properties[name] = val

  def GetProperty(self, name, default=None):
    return self._properties.get(name, default)

  def GetProperties(self):
    return self._properties
