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

package parser

import (
	"fmt"
	"io/ioutil"
	"mojom/mojom_parser/mojom"
	"os"
	"path/filepath"
)

///////////////////////////////////////////////////////////////////////
/// Type ParseDriver
//////////////////////////////////////////////////////////////////////

// A ParseDriver is used to parse a list of .mojom files.
//
// Construct a new ParseDriver via NewDriver() and then call ParseFiles()
// passing in the list of top-level .mojom files to be parsed. Any imported
// files will also be parsed.
//
// We attempt to find the file named by a given path, both top-level and
// imported, using the following algorithm:
// (1) If the specified path is an absolute path we use that path
// (2) Otherwise if the file was imported from another file we first attempt
// to find a file with the specified path relative to the directory of the
// importing file
// (3) Otherwise if the file was imported we attempt to find a file with the
// specified path relative to one of the specified import directories.
// (4) Otherwise we attempt to find a file with the specified path relative to
// the current working directory.
//
// After all files have been parsed the populated |MojomDescriptor| will be
// resovled, and then Mojo serialization data will be computed for use by
// the code generators.
//
// A poulated |MojomDescriptor| is returned.
// If there  was an error then the returned |err| will be non-nil.
//
// A ParseDriver may only be used once.
type ParseDriver struct {
	fileProvider     FileProvider
	fileExtractor    FileExtractor
	parseInvoker     ParseInvoker
	importDirs       []string
	debugMode        bool
	metaDataOnlyMode bool
}

// NewDriver consructs a new ParseDriver.
//
// importDirectories is a list of paths, either absolute or relative to the
// current working directory, of directories in which we should search for
// imported .mojom files.
//
// If debugMode is true we print to standard out the parse tree resulting
// from each file parsing. In non-debug mode the parsers do not explicitly
// construct a parse tree.
//
// If metaDataOnlyMode is true then:
// (1) The parsers will only parse the mojom file metadata (module statement,
// import statements, file-level attributes). The mojom declarations will not
// be parsed. The result will be as if the .mojom file did not have any mojom
// declarations. The resolution and validation phases will not be executed.
// (2) References to imported files will not be followed and imported files
// will not be parsed. Only explicitly specified files will be parsed.
// This implies that the |MojomFile|s will contain partial information about
// their imports. Each |ImportedFile| will contain its |SpecifiedName| but not
// its |CanonicalFileName|.
func NewDriver(importDirectories []string, debugMode, metaDataOnlyMode bool) *ParseDriver {
	fileProvider := new(OSFileProvider)
	fileProvider.importDirs = importDirectories
	return newDriver(importDirectories, debugMode, metaDataOnlyMode, fileProvider,
		DefaultFileExtractor(0), DefaultParseInvoker(0))
}

// This version of the factory is used in tests.
func newDriver(importDirectories []string, debugMode, metaDataOnlyMode bool, fileProvider FileProvider,
	fileExtractor FileExtractor, parseInvoker ParseInvoker) *ParseDriver {
	p := ParseDriver{fileProvider: fileProvider, fileExtractor: fileExtractor, parseInvoker: parseInvoker,
		importDirs: importDirectories, debugMode: debugMode, metaDataOnlyMode: metaDataOnlyMode}
	return &p

}

// Parses each of the given .mojom files and all of the files in the
// import graph rooted by each file. A single MojomDescriptor is created and
// populated with the result of parsing all of those files. If the parsing is
// successful then err will be nil.
//
// fileNames must not be nil or we will panic.
func (d *ParseDriver) ParseFiles(fileNames []string) (descriptor *mojom.MojomDescriptor, err error) {
	if fileNames == nil {
		// We panic instead of returning an error here because this would be a programming error
		// as opposed to an error in the input.
		panic("fileNames may not be nil.")
	}
	filesToProcess := make([]*FileReference, len(fileNames))
	descriptor = mojom.NewMojomDescriptor()
	for i, fileName := range fileNames {
		filesToProcess[i] = &FileReference{specifiedPath: fileName}
	}

	for len(filesToProcess) > 0 {
		currentFile := filesToProcess[0]
		filesToProcess = filesToProcess[1:]
		if err = d.fileProvider.findFile(currentFile); err != nil {
			return
		}

		var importedFrom *mojom.MojomFile = nil
		if currentFile.importedFrom != nil {
			importedFrom = currentFile.importedFrom.mojomFile
			// Tell the importing file about the absolute path of the imported file.
			// Note that we must do this even if the imported file has already been processed
			// because a given file may be imported by multiple files and each of those need
			// to be told about the absolute path of the imported file.
			importedFrom.SetCanonicalImportName(currentFile.specifiedPath, currentFile.absolutePath)
		}

		if !descriptor.ContainsFile(currentFile.absolutePath) {
			contents, fileReadError := d.fileProvider.provideContents(currentFile)
			if fileReadError != nil {
				err = fileReadError
				return
			}
			// topLevelFileName should be non-empty if and only if the current file is a top-level file.
			topLevelFileName := ""
			if importedFrom == nil {
				topLevelFileName = currentFile.specifiedPath
			}
			parser := MakeParser(currentFile.absolutePath, topLevelFileName,
				contents, descriptor, importedFrom)
			parser.SetDebugMode(d.debugMode)
			parser.SetMetaDataOnlyMode(d.metaDataOnlyMode)
			// Invoke parser.Parse() (but skip doing so in tests sometimes.)
			d.parseInvoker.invokeParse(&parser)

			if d.debugMode {
				fmt.Printf("\nParseTree for %s:", currentFile)
				fmt.Println(parser.GetParseTree())
			}

			if !parser.OK() {
				err = parser.GetError()
				return
			}
			currentFile.mojomFile = d.fileExtractor.extractMojomFile(&parser)
			if !d.metaDataOnlyMode {
				// In meta-data-only mode we do not follow import statements.
				for _, importedFile := range currentFile.mojomFile.Imports {
					// Note that it is important that we append all of the imported files here even
					// if some of them have already been processed. That is because when the imported
					// file is pulled from the queue it will be pre-processed during which time the
					// absolute path to the file will be discovered and this absolute path will be
					// set in |mojomFile| which is necessary for serializing mojomFile.
					filesToProcess = append(filesToProcess,
						&FileReference{importedFrom: currentFile, specifiedPath: importedFile.SpecifiedName})
				}
			}
		}
	}

	// Perform type and value resolution
	if err = descriptor.Resolve(); err != nil {
		return
	}

	// Compute enum value integers.
	if err = descriptor.ComputeEnumValueIntegers(); err != nil {
		return
	}

	// Compute data for generators.
	err = descriptor.ComputeDataForGenerators()
	return
}

type FileReference struct {
	mojomFile     *mojom.MojomFile
	importedFrom  *FileReference
	specifiedPath string
	absolutePath  string
	directoryPath string
}

func (f FileReference) String() string {
	if f.importedFrom != nil {
		return fmt.Sprintf("%s imported from file %s.",
			f.specifiedPath, f.importedFrom.specifiedPath)
	} else {
		return fmt.Sprintf("%s", f.specifiedPath)
	}
}

// FileExtractor is an abstraction that allows us to inject fake MojomFiles
// in tests.
type FileExtractor interface {
	extractMojomFile(parser *Parser) *mojom.MojomFile
}

type DefaultFileExtractor int

func (DefaultFileExtractor) extractMojomFile(parser *Parser) *mojom.MojomFile {
	return parser.GetMojomFile()
}

// ParseInvoker is an abstraction that allows us to skip actually invoking
// the parse method in tests of the driver.
type ParseInvoker interface {
	invokeParse(parser *Parser)
}

type DefaultParseInvoker int

func (DefaultParseInvoker) invokeParse(parser *Parser) {
	parser.Parse()
}

// FileProvider is an abstraction that allows us to mock out the file system
// in tests.
type FileProvider interface {
	provideContents(fileRef *FileReference) (contents string, fileReadError error)

	// findFile attempts to locate the file specified by the |specifiedPath|
	// field of |fileRef|, taking into consideration also the |importedFrom|
	// field. If the file can be located then the |absolutePath| and
	// |directoryPath| path fields will be set and nil is returned.
	// Otherwise a non-nil error is returned.
	findFile(fileRef *FileReference) error
}

type OSFileProvider struct {
	importDirs []string
}

func (p OSFileProvider) provideContents(fileRef *FileReference) (contents string, fileReadError error) {
	data, err := ioutil.ReadFile(fileRef.absolutePath)
	if err != nil {
		fileReadError = fmt.Errorf("\nError while reading %s: %s\n\n", fileRef, err)
	} else {
		contents = string(data)
	}
	return
}

// findFile populates the |absolutePath| and |directoryPath| fields of
// *fileRef. It attempts to find a file on the file system named by the |specifiedPath|
// field using the search algorithm described at the top of this file.
func (p *OSFileProvider) findFile(fileRef *FileReference) (err error) {
	// If this FileReference has already been processed there is nothing to do.
	if len(fileRef.absolutePath) > 0 {
		return
	}

	// If the specified path is already absolute we use that path.
	if filepath.IsAbs(fileRef.specifiedPath) {
		fileRef.absolutePath = fileRef.specifiedPath
		fileRef.directoryPath = filepath.Dir(fileRef.absolutePath)
		return
	}

	// If the file was imported from another file...
	if fileRef.importedFrom != nil {
		// First attempt to find the file relative to the directory of the
		// importing file.
		attemptedName := filepath.Join(fileRef.importedFrom.directoryPath, fileRef.specifiedPath)
		if isFile(attemptedName) {
			fileRef.absolutePath, err = filepath.Abs(attemptedName)
			fileRef.directoryPath = filepath.Dir(fileRef.absolutePath)
			return
		}

		// then search in the specified import directories.
		if p.importDirs != nil {
			for _, dir := range p.importDirs {
				attemptedName := filepath.Join(dir, fileRef.specifiedPath)
				if isFile(attemptedName) {
					fileRef.absolutePath, err = filepath.Abs(attemptedName)
					fileRef.directoryPath = filepath.Dir(fileRef.absolutePath)
					return
				}
			}

		}
	}

	// Finally look in the current working directory.
	if isFile(fileRef.specifiedPath) {
		if fileRef.absolutePath, err = filepath.Abs(fileRef.specifiedPath); err != nil {
			return err
		}
		fileRef.directoryPath = filepath.Dir(fileRef.absolutePath)
		return
	}

	return fmt.Errorf("File not found: %s", fileRef)
}

func isFile(path string) bool {
	info, err := os.Stat(path)
	if err != nil {
		return false
	}
	return !info.IsDir()
}
