// Licensed to 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. Apache Software Foundation (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 instrument

import (
	"go/parser"
	"os"
	"path/filepath"
	"strings"

	"github.com/dave/dst"
	"github.com/dave/dst/decorator"
	"github.com/dave/dst/dstutil"

	"github.com/sirupsen/logrus"

	"github.com/apache/skywalking-go/tools/go-agent/instrument/agentcore"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/entry"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/logger"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/plugins"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/reporter"
	"github.com/apache/skywalking-go/tools/go-agent/instrument/runtime"
	"github.com/apache/skywalking-go/tools/go-agent/tools"
)

var instruments = []api.Instrument{
	runtime.NewInstrument(),
	agentcore.NewInstrument(),
	reporter.NewGRPCInstrument(),
	entry.NewInstrument(),
	logger.NewInstrument(),
	plugins.NewInstrument(),
}

func Execute(opts *api.CompileOptions, args []string) ([]string, error) {
	// if the options is invalid, just ignore
	if !opts.IsValid() {
		return args, nil
	}

	// init the logger for the instrument
	loggerFile, err := initLogger(opts)
	if err != nil {
		return nil, err
	}
	defer loggerFile.Close()
	logrus.Infof("executing instrument with args: %v", args)

	return execute0(opts, args)
}

func execute0(opts *api.CompileOptions, args []string) ([]string, error) {
	// find the instrument
	var inst api.Instrument
	for _, ins := range instruments {
		if ins.CouldHandle(opts) {
			inst = ins
			break
		}
	}
	if inst == nil {
		return args, nil
	}

	var buildDir = filepath.Dir(opts.Output)

	// instrument existing files
	if err := instrumentFiles(buildDir, inst, args); err != nil {
		return nil, err
	}

	// write extra files if exist
	files, err := inst.WriteExtraFiles(buildDir)
	if err != nil {
		return nil, err
	}
	if len(files) > 0 {
		args = append(args, files...)
	}

	return args, nil
}

func instrumentFiles(buildDir string, inst api.Instrument, args []string) error {
	// parse files
	parsedFiles, err := parseFilesInArgs(args)
	if err != nil {
		return err
	}

	allFiles := make([]*dst.File, 0)
	for _, f := range parsedFiles {
		allFiles = append(allFiles, f.dstFile)
	}

	// filter and edit the files
	instrumentedFiles := make([]string, 0)
	for path, info := range parsedFiles {
		hasInstruted := false
		dstutil.Apply(info.dstFile, func(cursor *dstutil.Cursor) bool {
			if inst.FilterAndEdit(path, info.dstFile, cursor, allFiles) {
				hasInstruted = true
			}
			return true
		}, func(cursor *dstutil.Cursor) bool {
			return true
		})

		if hasInstruted {
			instrumentedFiles = append(instrumentedFiles, path)
		}
	}

	// write instrumented files to the build directory
	for _, updateFileSrc := range instrumentedFiles {
		info := parsedFiles[updateFileSrc]
		filename := filepath.Base(updateFileSrc)
		dest := filepath.Join(buildDir, filename)
		debugInfo, err := tools.BuildDSTDebugInfo(updateFileSrc, nil)
		if err != nil {
			return err
		}
		if err := tools.WriteDSTFile(dest, info.dstFile, debugInfo); err != nil {
			return err
		}
		if err := inst.AfterEnhanceFile(updateFileSrc, dest); err != nil {
			return err
		}
		args[info.argsIndex] = dest
	}

	return nil
}

func parseFilesInArgs(args []string) (map[string]*fileInfo, error) {
	parsedFiles := make(map[string]*fileInfo)
	for inx, path := range args {
		// only process the go file
		if !strings.HasSuffix(path, ".go") {
			continue
		}

		// parse the file
		file, err := decorator.ParseFile(nil, path, nil, parser.ParseComments)
		if err != nil {
			return nil, err
		}

		parsedFiles[path] = &fileInfo{
			argsIndex: inx,
			dstFile:   file,
		}
	}

	return parsedFiles, nil
}

func initLogger(opts *api.CompileOptions) (*os.File, error) {
	logrus.SetFormatter(&logrus.TextFormatter{
		DisableColors: true,
		FullTimestamp: true,
	})
	file, err := os.OpenFile(filepath.Join(opts.CompileBaseDir(), "instrument.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
	if err != nil {
		return nil, err
	}
	logrus.SetOutput(file)

	return file, nil
}

type fileInfo struct {
	argsIndex int
	dstFile   *dst.File
}
