// Copyright 2020 The Fuchsia 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 main

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"image"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/google/subcommands"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"

	fg "go.fuchsia.dev/fuchsia/tools/femu-control/femu-grpc"
)

type recordScreenCmd struct {
	format      string
	numFrames   uint
	duration    time.Duration
	imageOutput string
	verbose     bool
}

func (*recordScreenCmd) Name() string     { return "record_screen" }
func (*recordScreenCmd) Synopsis() string { return "Record screen to a sequence of image files" }

func (*recordScreenCmd) Usage() string {
	return `record_screen: Record FEMU screen contents to a sequence of image files.

Usage:

record_screen [-num-frames <#>] [-duration <d>] [-v]
        [-out path/file%.jpg|file%.png|file.gif]

At least one of -num-frames and -duration arguments should be present.

Output file can be jpg, png or gif format. For jpg/png files, filename
should contain a '%' symbol representing image number.

Flags:
`
}

func (c *recordScreenCmd) SetFlags(f *flag.FlagSet) {
	f.UintVar(&c.numFrames, "num-frames", 0, "maximum number of captured frames")
	f.DurationVar(&c.duration, "duration", time.Duration(0), "maximum recording time "+
		"(format should be acceptable to time.ParseDuration; e.g. 5.5s, 1m45s, 300ms)")
	f.StringVar(&c.imageOutput, "out", "./screenshot-%.png", "screenshot output path")
	f.BoolVar(&c.verbose, "v", false, "verbose mode (log screenshot filenames)")
}

func (c *recordScreenCmd) ValidateArgs() error {
	if c.imageOutput == "" {
		return fmt.Errorf("-out flag is required")
	}

	if c.numFrames == 0 && c.duration == 0 {
		return fmt.Errorf("-num-frames and -duration cannot be both zero")
	}

	var err error = nil
	c.imageOutput, err = filepath.Abs(c.imageOutput)
	if err != nil {
		return fmt.Errorf("cannot get absolute path of '%s': %v", c.imageOutput, err)
	}
	dir, file := path.Split(c.imageOutput)
	fileInfo, err := os.Stat(dir)
	switch {
	case err != nil && !os.IsNotExist(err):
		return fmt.Errorf("path %s invalid: %v", dir, err)
	case err == nil && !fileInfo.IsDir():
		return fmt.Errorf("path %s is not a directory", dir)
	case err == nil && fileInfo.IsDir() && syscall.Access(dir, syscall.O_RDWR) != nil:
		return fmt.Errorf("path %s is not writeable", dir)
	}

	ext := filepath.Ext(file)
	basename := filepath.Base(file)

	if ext != ".gif" && strings.Count(basename, "%") != 1 {
		newFileName := basename[0:len(basename)-len(ext)] + "%" + ext
		c.imageOutput = path.Join(dir, newFileName)
		fmt.Fprintf(os.Stderr, "filename '%s' doesn't contain '%%', renamed to '%s'", file, newFileName)
	}

	switch ext {
	case ".jpeg", ".jpg", ".gif", ".png":
		break
	case "":
		return fmt.Errorf("filename '%s' doesn't contain any extension!", file)
	default:
		return fmt.Errorf("filename '%s' has unsupported extension: %s. "+
			"supported extensions are jpeg, jpg, gif, and png.", file, ext)
	}

	return nil
}

func genScreenshotFileName(name string, i int, max int) string {
	nameSubs := strings.Split(name, "%")
	prefix, suffix := nameSubs[0], nameSubs[1]

	maxDigits := len(strconv.Itoa(max))
	return fmt.Sprintf("%s%0*d%s", prefix, maxDigits, i, suffix)
}

func imageToPaletted(img image.Image) *image.Paletted {
	numColors := 256
	b := img.Bounds()

	pm := image.NewPaletted(b, palette.Plan9[:numColors])
	draw.FloydSteinberg.Draw(pm, b, img, b.Min)

	return pm
}

func (c *recordScreenCmd) run(ctx context.Context) error {
	dir, name := path.Split(c.imageOutput)
	nameSubs := strings.Split(name, ".")
	c.format = strings.ToLower(nameSubs[len(nameSubs)-1])

	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("error while creating directory %s: %v", dir, err)
	}

	client := ctx.Value("client").(fg.FemuGrpcClientInterface)
	if client == nil {
		return fmt.Errorf("FEMU gRPC client not found")
	}

	opts, err := fg.NewStreamScreenOpts("PNG", c.numFrames, c.duration)
	if err != nil {
		return fmt.Errorf("cannot create StreamScreenOpts: %v", err)
	}

	frames, err := client.StreamScreen(opts)
	if err != nil {
		return fmt.Errorf("error while FEMU gRPC streaming screen: %v", err)
	}

	var g *gif.GIF
	if c.format == "gif" {
		g = &gif.GIF{}
	}

	// Encode and store frames to images
	for i, b := range frames.Images {
		if c.format == "gif" {
			r := bytes.NewReader(b)
			img, err := png.Decode(r)
			if err != nil {
				return fmt.Errorf("error while decoding PNG: %v", err)
			}

			pm := imageToPaletted(img)

			g.Image = append(g.Image, pm)
			g.Delay = append(g.Delay, 10)

			continue
		}

		fn := genScreenshotFileName(name, i, len(frames.Images)-1)
		fpath := path.Join(dir, fn)

		if c.format == "jpg" || c.format == "jpeg" {
			r := bytes.NewReader(b)
			img, err := png.Decode(r)
			if err != nil {
				return fmt.Errorf("error while decoding PNG: %v", err)
			}

			f, err := os.Create(fpath)
			defer f.Close()
			if err != nil {
				return fmt.Errorf("error while creating file %s: %v", fpath, err)
			}

			err = jpeg.Encode(f, img, &jpeg.Options{Quality: 100})
			if err != nil {
				return fmt.Errorf("error while encoding and writing JPEG: %v", err)
			}

			if c.verbose {
				fmt.Println(fpath)
			}
			continue
		}

		if c.format == "png" {
			err := ioutil.WriteFile(fpath, b, 0644)
			if err != nil {
				return fmt.Errorf("error while writing file: %v", err)
			}

			if c.verbose {
				fmt.Println(fpath)
			}
			continue
		}
	}

	if c.format == "gif" {
		f, err := os.Create(c.imageOutput)
		defer f.Close()
		if err != nil {
			return fmt.Errorf("error while creating file %s: %v", c.imageOutput, err)
		}

		err = gif.EncodeAll(f, g)
		if err != nil {
			return fmt.Errorf("error while encoding and writing GIF: %v", err)
		}

		if c.verbose {
			fmt.Println(c.imageOutput)
		}
	}
	return nil
}

func (c *recordScreenCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	if err := c.ValidateArgs(); err != nil {
		logger.Errorf(ctx, err.Error())
		return subcommands.ExitUsageError
	}

	if err := c.run(ctx); err != nil {
		logger.Errorf(ctx, err.Error())
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}
