// Copyright (C) 2016 The Android Open Source Project
//
// Licensed 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 parser

import (
	"fmt"
	"path/filepath"
	"strings"

	"android.googlesource.com/platform/tools/gpu/framework/stringtable"
	"android.googlesource.com/platform/tools/gpu/framework/stringtable/minidown"
	"android.googlesource.com/platform/tools/gpu/framework/stringtable/minidown/node"
)

// Parse parses the given string table file.
func Parse(filename, data string) (*stringtable.StringTable, []error) {
	var errs []error

	// Start by parsing the minidown
	minidown, parseErrs := minidown.Parse(filename, data)
	if len(parseErrs) > 0 {
		errs = append(errs, parseErrs)
	}

	// Process the minidown into stringtable entries.
	entries, processErrs := process(minidown)
	if len(processErrs) > 0 {
		errs = append(errs, processErrs...)
	}

	table := &stringtable.StringTable{
		Info: stringtable.Info{
			CultureCode: strings.Split(filepath.Base(filename), ".")[0],
		},
		Entries: entries,
	}
	return table, errs
}

func process(in node.Node) (map[string]stringtable.Node, []error) {
	var errs []error
	table := map[string]stringtable.Node{}

	var current string // Name of the current entry.
	newlines := 0      // Number of pending newlines.

	add := func(n node.Node) {
		if len(current) == 0 {
			return // No entry assigned yet. Perhaps a file header message?
		}

		// Convert the minidown node to a stringtable node.
		converted, e := convert(n)
		errs = append(errs, e...)

		// Check to see if this is a new entry, or appending to an existing.
		existing := table[current]
		if existing == nil {
			// New entry. Simply assign to the table.
			table[current] = converted
			newlines = 0
			return
		}

		block, ok := existing.(*stringtable.Block)
		if !ok {
			// Multiple nodes for entry. Box first entry into a block.
			block = &stringtable.Block{Children: []stringtable.Node{existing}}
		}

		// Add any pending line breaks
		if newlines > 0 {
			block.Children = append(block.Children, &stringtable.LineBreak{
				Lines: uint32(newlines),
			})
			newlines = 0
		}

		// Add new node to the block.
		block.Children = append(block.Children, converted)

		// Update table.
		table[current] = block
	}

	root, ok := in.(*node.Block)
	if !ok {
		return nil, []error{fmt.Errorf("Expected root to be a block, instead got %T", in)}
	}

	for _, n := range root.Children {
		switch n := n.(type) {
		case *node.NewLine:
			newlines++

		case *node.Heading:
			// Check for a new table entry. These are declared as H1 headings.
			if n.Scale == 1 {
				if text, ok := n.Body.(*node.Text); ok {
					// Change current.
					current = text.Text

					// Check for duplicates.
					if _, dup := table[current]; dup {
						errs = append(errs, fmt.Errorf("Duplicate stringtable entry '%s'", current))
					}
				} else {
					errs = append(errs, fmt.Errorf("Entry name must be simple text, instead got %T", n.Body))
				}
			} else {
				add(n) // A heading, but not H1. Add to existing entry.
			}

		default:
			add(n)
		}
	}
	return table, errs
}

func convert(in node.Node) (stringtable.Node, []error) {
	switch in := in.(type) {
	case *node.Text:
		return &stringtable.Text{Text: in.Text}, nil

	case *node.Whitespace:
		return &stringtable.Whitespace{}, nil

	case *node.Link:
		body, errsA := convert(in.Body)
		target, errsB := convert(in.Target)
		return &stringtable.Link{Body: body, Target: target}, append(errsA, errsB...)

	case *node.Tag:
		return &stringtable.Parameter{Key: in.Identifier}, nil

	default:
		return nil, []error{fmt.Errorf("Stringtable does not currently support %T", in)}
	}
}
