# Copyright 2015 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.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import symbol
import token

from py_utils.refactor import snippet
from py_utils.refactor.annotated_symbol import base_symbol
from six.moves import range # pylint: disable=redefined-builtin
from six.moves import zip_longest # pylint: disable=redefined-builtin


__all__ = [
    'Reference',
]


class Reference(base_symbol.AnnotatedSymbol):
  @classmethod
  def Annotate(cls, nodes):
    if not nodes:
      return None
    if nodes[0].type != symbol.atom:
      return None
    if not nodes[0].children or nodes[0].children[0].type != token.NAME:
      return None

    for i in range(1, len(nodes)):
      if not nodes:
        break
      if nodes[i].type != symbol.trailer:
        break
      if len(nodes[i].children) != 2:
        break
      if (nodes[i].children[0].type != token.DOT or
          nodes[i].children[1].type != token.NAME):
        break
    else:
      i = len(nodes)

    return [cls(nodes[:i])] + nodes[i:]

  def __init__(self, children):
    super(Reference, self).__init__(-1, children)

  @property
  def type_name(self):
    return 'attribute_reference'

  @property
  def value(self):
    return ''.join(token_snippet.value
                   for child in self.children
                   for token_snippet in child.children)

  @value.setter
  def value(self, value):
    value_parts = value.split('.')

    # If we have too many children, cut the list down to size.
    # pylint: disable=attribute-defined-outside-init
    self._children = self._children[:len(value_parts)]

    # Update child nodes.
    for child, value_part in zip_longest(self._children, value_parts):
      if child:
        # Modify existing children. This helps preserve comments and spaces.
        child.children[-1].value = value_part
      else:
        # Add children as needed.
        token_snippets = [
            snippet.TokenSnippet.Create(token.DOT, '.'),
            snippet.TokenSnippet.Create(token.NAME, value_part),
        ]
        self._children.append(snippet.Symbol(symbol.trailer, token_snippets))
