#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  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 License for the
#  specific language governing permissions and limitations
#  under the License.

""" query.py """
import tornado.httpclient
import tornado.gen

from heron.tools.tracker.src.python.query_operators import *


####################################################################
# Parsing and executing the query string.
####################################################################

# pylint: disable=no-self-use
class Query(object):
  """Execute the query for metrics. Uses Tracker to get
     individual metrics that are part of the query.
     Example usage:
        query = Query(tracker)
        result = query.execute(tmaster, query_string)"""
  # pylint: disable=undefined-variable
  def __init__(self, tracker):
    self.tracker = tracker
    self.operators = {
        'TS':TS,
        'DEFAULT':Default,
        'MAX':Max,
        'SUM':Sum,
        'SUBTRACT':Subtract,
        'PERCENTILE':Percentile,
        'DIVIDE':Divide,
        'MULTIPLY':Multiply,
        'RATE':Rate
    }


  # pylint: disable=attribute-defined-outside-init, no-member
  @tornado.gen.coroutine
  def execute_query(self, tmaster, query_string, start, end):
    """ execute query """
    if not tmaster:
      raise Exception("No tmaster found")
    self.tmaster = tmaster
    root = self.parse_query_string(query_string)
    metrics = yield root.execute(self.tracker, self.tmaster, start, end)
    raise tornado.gen.Return(metrics)

  def find_closing_braces(self, query):
    """Find the index of the closing braces for the opening braces
    at the start of the query string. Note that first character
    of input string must be an opening braces."""
    if query[0] != '(':
      raise Exception("Trying to find closing braces for no opening braces")
    num_open_braces = 0
    for i in range(len(query)):
      c = query[i]
      if c == '(':
        num_open_braces += 1
      elif c == ')':
        num_open_braces -= 1
      if num_open_braces == 0:
        return i
    raise Exception("No closing braces found")

  def get_sub_parts(self, query):
    """The subparts are seperated by a comma. Make sure
    that commas inside the part themselves are not considered."""
    parts = []
    num_open_braces = 0
    delimiter = ','
    last_starting_index = 0
    for i in range(len(query)):
      if query[i] == '(':
        num_open_braces += 1
      elif query[i] == ')':
        num_open_braces -= 1
      elif query[i] == delimiter and num_open_braces == 0:
        parts.append(query[last_starting_index: i].strip())
        last_starting_index = i + 1
    parts.append(query[last_starting_index:].strip())
    return parts

  def parse_query_string(self, query):
    """Returns a parse tree for the query, each of the node is a
    subclass of Operator. This is both a lexical as well as syntax analyzer step."""
    if not query:
      return None
    # Just braces do not matter
    if query[0] == '(':
      index = self.find_closing_braces(query)
      # This must be the last index, since this was an NOP starting brace
      if index != len(query) - 1:
        raise Exception("Invalid syntax")
      else:
        return self.parse_query_string(query[1:-1])
    start_index = query.find("(")
    # There must be a ( in the query
    if start_index < 0:
      # Otherwise it must be a constant
      try:
        constant = float(query)
        return constant
      except ValueError:
        raise Exception("Invalid syntax")
    token = query[:start_index]
    if token not in self.operators:
      raise Exception("Invalid token: " + token)

    # Get sub components
    rest_of_the_query = query[start_index:]
    braces_end_index = self.find_closing_braces(rest_of_the_query)
    if braces_end_index != len(rest_of_the_query) - 1:
      raise Exception("Invalid syntax")
    parts = self.get_sub_parts(rest_of_the_query[1:-1])

    # parts are simple strings in this case
    if token == "TS":
      # This will raise exception if parts are not syntactically correct
      return self.operators[token](parts)

    children = []
    for part in parts:
      children.append(self.parse_query_string(part))

    # Make a node for the current token
    node = self.operators[token](children)
    return node
