// Copyright (C) 2014 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 api holds the main interface to the api language libraries.
// It provides functions for going from api files to abstract syntax trees and
// processed semantic trees.
package api

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"sort"

	"android.googlesource.com/platform/tools/gpu/api/ast"
	"android.googlesource.com/platform/tools/gpu/api/parser"
	"android.googlesource.com/platform/tools/gpu/api/resolver"
	"android.googlesource.com/platform/tools/gpu/api/semantic"
	"android.googlesource.com/platform/tools/gpu/parse"
)

// Processor holds the state when resolving multiple api files.
type Processor struct {
	Parsed   map[string]*ast.API
	Resolved map[string]*semantic.API
}

// DefaultProcessor is the Processor used in the package level functions.
// Most applications will not need multiple instances of a Processor, and can
// just use this one.
var DefaultProcessor = Processor{
	Parsed:   map[string]*ast.API{},
	Resolved: map[string]*semantic.API{},
}

// Parse parses the api file with the DefaultProcessor.
// See Processor.Parse for details.
func Parse(apiname string) (*ast.API, parse.ErrorList) {
	return DefaultProcessor.Parse(apiname)
}

// Parse returns an ast that represents the supplied filename.
// It if the file has already been parsed, the cached ast will be returned,
// otherwise it invokes parser.Parse on the content of the supplied file name.
func (p *Processor) Parse(path string) (*ast.API, parse.ErrorList) {
	if api, ok := p.Parsed[path]; ok {
		return api, nil
	}
	info, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, parse.ErrorList{parse.Error{Message: err.Error()}}
	}
	return parser.Parse(path, string(info))
}

// Resolve resolves the api file with the DefaultProcessor.
// See Processor.Resolve for details.
func Resolve(apiname string, mappings resolver.ASTToSemantic) (*semantic.API, parse.ErrorList) {
	return DefaultProcessor.Resolve(apiname, mappings)
}

// Resolve returns a semantic.API that represents the supplied api file name.
// If the file has already been resolved, the cached semantic tree is returned,
// otherwise the file and all dependant files are parsed using Processor.Parse.
// Recursive calls are made to Resolve for all named imports, and then finally
// the ast and all included ast's are handed to resolver.Resolve to do semantic
// processing.
func (p *Processor) Resolve(apiname string, mappings resolver.ASTToSemantic) (*semantic.API, parse.ErrorList) {
	absname, err := filepath.Abs(apiname)
	if err != nil {
		return nil, parse.ErrorList{parse.Error{Message: err.Error()}}
	}
	wd, name := filepath.Split(absname)
	return p.resolve(wd, name, mappings)
}

func (p *Processor) resolve(wd, name string, mappings resolver.ASTToSemantic) (*semantic.API, parse.ErrorList) {
	absname := filepath.Join(wd, name)
	if api, ok := p.Resolved[absname]; ok {
		if api == nil { // reentry detected
			return nil, parse.ErrorList{parse.Error{
				Message: fmt.Sprintf("Recursive import %s", absname)},
			}
		}
		return api, nil
	}
	p.Resolved[absname] = nil // mark to prevent reentry
	// Parse all the includes
	includes := map[string]*ast.API{}
	errs := p.include(includes, wd, name)
	if len(errs) > 0 {
		return nil, errs
	}
	// Build a sorted list of includes
	names := make(sort.StringSlice, 0, len(includes))
	for name := range includes {
		names = append(names, name)
	}
	names.Sort()
	list := make([]*ast.API, len(names))
	for i, name := range names {
		list[i] = includes[name]
	}
	// Resolve all the imports
	imports := &semantic.Symbols{}
	importPaths := map[string]string{}
	for _, api := range list {
		for _, i := range api.Imports {
			if i.Name == nil {
				// unnamed imports have already been included
				continue
			}
			path := filepath.Join(wd, i.Path.Value)
			if importedPath, seen := importPaths[i.Name.Value]; seen {
				if path == importedPath {
					// import with same path and name already included
					continue
				}
				return nil, parse.ErrorList{parse.Error{
					Message: fmt.Sprintf("Import name '%s' used for different paths (%s != %s)",
						i.Name.Value, path, importedPath)},
				}
			}
			api, errs := p.resolve(wd, i.Path.Value, mappings)
			if len(errs) > 0 {
				return nil, errs
			}
			imports.Add(i.Name.Value, api)
			importPaths[i.Name.Value] = path
		}
	}
	// Now resolve the api set as a single unit
	api, errs := resolver.Resolve(list, imports, mappings)
	if len(errs) == 0 {
		p.Resolved[absname] = api
	}
	return api, errs
}

func (p *Processor) include(includes map[string]*ast.API, wd string, apiname string) parse.ErrorList {
	absname, err := filepath.Abs(filepath.Join(wd, apiname))
	if err != nil {
		return parse.ErrorList{parse.Error{Message: err.Error()}}
	}
	if _, seen := includes[absname]; seen {
		return nil
	}
	api, errs := p.Parse(absname)
	if len(errs) > 0 {
		return errs
	}
	includes[absname] = api
	for _, i := range api.Imports {
		if i.Name != nil {
			// named imports don't get merged
			continue
		}
		errs := p.include(includes, wd, i.Path.Value)
		if len(errs) > 0 {
			return errs
		}
	}
	return nil
}
