/*
 * 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.
 */

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	htrace "org/apache/htrace/client"
	"org/apache/htrace/common"
	"strings"
	"unicode"
)

// Convert a string into a whitespace-separated sequence of strings.
func tokenize(str string) []string {
	prevQuote := rune(0)
	f := func(c rune) bool {
		switch {
		case c == prevQuote:
			prevQuote = rune(0)
			return false
		case prevQuote != rune(0):
			return false
		case unicode.In(c, unicode.Quotation_Mark):
			prevQuote = c
			return false
		default:
			return unicode.IsSpace(c)
		}
	}
	return strings.FieldsFunc(str, f)
}

// Parses a query string in the format of a series of
// [TYPE] [OPERATOR] [CONST] tuples, joined by AND statements.
type predicateParser struct {
	tokens   []string
	curToken int
}

func (ps *predicateParser) Parse() (*common.Predicate, error) {
	if ps.curToken > len(ps.tokens) {
		return nil, nil
	}
	if ps.curToken > 0 {
		if strings.ToLower(ps.tokens[ps.curToken]) != "and" {
			return nil, errors.New(fmt.Sprintf("Error parsing on token %d: "+
				"expected predicates to be joined by 'and', but found '%s'",
				ps.curToken, ps.tokens[ps.curToken]))
		}
		ps.curToken++
		if ps.curToken > len(ps.tokens) {
			return nil, errors.New(fmt.Sprintf("Nothing found after 'and' at "+
				"token %d", ps.curToken))
		}
	}
	field := common.Field(ps.tokens[ps.curToken])
	if !field.IsValid() {
		return nil, errors.New(fmt.Sprintf("Invalid field specifier at token %d.  "+
			"Can't understand %s.  Valid field specifiers are %v", ps.curToken,
			ps.tokens[ps.curToken], common.ValidFields()))
	}
	ps.curToken++
	if ps.curToken > len(ps.tokens) {
		return nil, errors.New(fmt.Sprintf("Nothing found after field specifier "+
			"at token %d", ps.curToken))
	}
	op := common.Op(ps.tokens[ps.curToken])
	if !op.IsValid() {
		return nil, errors.New(fmt.Sprintf("Invalid operation specifier at token %d.  "+
			"Can't understand %s.  Valid operation specifiers are %v", ps.curToken,
			ps.tokens[ps.curToken], common.ValidOps()))
	}
	ps.curToken++
	if ps.curToken > len(ps.tokens) {
		return nil, errors.New(fmt.Sprintf("Nothing found after field specifier "+
			"at token %d", ps.curToken))
	}
	val := ps.tokens[ps.curToken]
	return &common.Predicate{Op: op, Field: field, Val: val}, nil
}

func parseQueryString(str string) ([]common.Predicate, error) {
	ps := predicateParser{tokens: tokenize(str)}
	preds := make([]common.Predicate, 0)
	for {
		pred, err := ps.Parse()
		if pred == nil {
			break
		}
		if err != nil {
			return nil, err
		}
	}
	if len(preds) == 0 {
		return nil, errors.New("Empty query string")
	}
	return preds, nil
}

// Send a query from a query string.
func doQueryFromString(hcl *htrace.Client, str string, lim int) error {
	query := &common.Query{Lim: lim}
	var err error
	query.Predicates, err = parseQueryString(str)
	if err != nil {
		return err
	}
	return doQuery(hcl, query)
}

// Send a query from a raw JSON string.
func doRawQuery(hcl *htrace.Client, str string) error {
	jsonBytes := []byte(str)
	var query common.Query
	err := json.Unmarshal(jsonBytes, &query)
	if err != nil {
		return errors.New(fmt.Sprintf("Error parsing provided JSON: %s\n", err.Error()))
	}
	return doQuery(hcl, &query)
}

// Send a query.
func doQuery(hcl *htrace.Client, query *common.Query) error {
	if *verbose {
		qbytes, err := json.Marshal(*query)
		if err != nil {
			qbytes = []byte("marshaling error: " + err.Error())
		}
		fmt.Printf("Sending query: %s\n", string(qbytes))
	}
	spans, err := hcl.Query(query)
	if err != nil {
		return err
	}
	if *verbose {
		fmt.Printf("%d results...\n", len(spans))
	}
	for i := range spans {
		fmt.Printf("%s\n", spans[i].ToJson())
	}
	return nil
}
