package main

import (
	"archive/tar"
	"bufio"
	"bytes"
	"compress/gzip"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/zhyee/zipstream"
)

type Prism struct {
	app *App
}



func (Prism) CheckInstalled() bool {
	path, _ := os.UserConfigDir()
	_, err := os.Stat(filepath.Join(path, "FCLauncher", "prism"))
	if err == nil {
		return true
	} else {
		return false
	}
}

func (p *Prism) Install() {
	suffix := "lin.tar.gz"
	shortSuffix := "lin"
	if runtime.GOOS == "windows" {
		suffix = "win.zip"
		shortSuffix = "win"
	}
	buff := new(bytes.Buffer)
	HttpDownload("prism/prism-"+suffix, buff, p.app.Ctx)
	path, _ := os.UserConfigDir()
	os.MkdirAll(filepath.Join(path, "FCLauncher", "prism"), 0755)
	if runtime.GOOS == "windows" {
		zr := zipstream.NewReader(buff)
		for {
			entry, err := zr.GetNextEntry()
			if err == io.EOF {
				break
			}
			if err != nil {
				return
			}
			target := filepath.Join(path, "FCLauncher", "prism", entry.Name)
			if !entry.IsDir() {
				rc, err := entry.Open()
				if err != nil {
					return
				}
				f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, entry.FileInfo().Mode())
				if err != nil {
					return
				}
				if _, err := io.Copy(f, rc); err != nil {
					return
				}
				f.Close()
				rc.Close()
			} else {
				if _, err := os.Stat(target); err != nil {
					if err := os.MkdirAll(target, 0755); err != nil {
						return
					}
				}
			}
		}
	} else {
		gzip, _ := gzip.NewReader(buff)
		defer gzip.Close()
		tr := tar.NewReader(gzip)
	out:
		for {
			header, err := tr.Next()
			switch {
			case err == io.EOF:
				break out
			case err != nil:
				return
			case header == nil:
				continue
			}
			target := filepath.Join(path, "FCLauncher", "prism", header.Name)
			switch header.Typeflag {
			case tar.TypeDir:
				if _, err := os.Stat(target); err != nil {
					if err := os.MkdirAll(target, 0755); err != nil {
						return
					}
				}
			case tar.TypeReg:
				f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
				if err != nil {
					return
				}
				if _, err := io.Copy(f, tr); err != nil {
					return
				}
				f.Close()
			}
		}

	}
	dir, _ := os.UserConfigDir()
	buff = new(bytes.Buffer)
	HttpDownload("prism/prismlauncher.cfg", buff, nil)
	scanner := bufio.NewScanner(buff)
	f, _ := os.OpenFile(filepath.Join(dir, "FCLauncher", "prism", "prismlauncher.cfg"), os.O_CREATE|os.O_RDWR, 0755)
	defer f.Close()
	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "JavaPath") {
			line = fmt.Sprintf("JavaPath=%s/FCLauncher/java/java-21-%s", strings.ReplaceAll(dir, "\\", "/"), shortSuffix)
		}
		if strings.HasPrefix(line, "LastHostname") {
			host, _ := os.Hostname()
			line = fmt.Sprintf("LastHostname=%s", host)
		}
		f.WriteString(line + "\n")
	}
}



func (Prism)GetInstanceDir() string{
	dir, _ := os.UserConfigDir()
	return filepath.Join(dir, "FCLauncher", "prism", "instances")
}

func (Prism)getExecutableName() string {
	execName := "PrismLauncher"
	if runtime.GOOS == "windows" {
		execName = "prismlauncher.exe"
	}
	return execName
}

func (p *Prism)ImportModpack(path string) {
	dir, _ := os.UserConfigDir()
	child := exec.Command(filepath.Join(dir, "FCLauncher", "prism", p.getExecutableName()), "-I", path)
	child.Start()
	tokens := strings.Split(path, string(os.PathSeparator))
	versionPath := filepath.Join(dir, "FCLauncher", "prism", "instances",strings.Split(tokens[len(tokens)-1], ".")[0], ".minecraft", "version.txt")
	for {
		time.Sleep(time.Second * 3)
		if _, err := os.Stat(versionPath); err == nil {
			break
		}
	}
	child.Process.Kill()
}

func (p *Prism)LaunchInstance(instance Instance) {
	p.app.Status(fmt.Sprintf("Launching %s", instance.InstanceName))
	dir, _ := os.UserConfigDir()
	child := exec.Command(filepath.Join(dir, "FCLauncher", "prism", p.getExecutableName()), "-l", instance.InstanceName)
	child.Start()
}
