package bilinovel

import (
	"archive/zip"
	"io"
	"log"
	"os"
	"path/filepath"
)

func CreateEpub(path string) error {
	log.Printf("Creating epub for %s", path)

	savePath := path + ".epub"
	zipFile, err := os.Create(savePath)
	if err != nil {
		return err
	}
	defer zipFile.Close()

	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	err = addStringToZip(zipWriter, "mimetype", "application/epub+zip", zip.Store)
	if err != nil {
		return err
	}

	err = addDirContentToZip(zipWriter, path, zip.Deflate)
	if err != nil {
		return err
	}

	err = addStringToZip(zipWriter, "OEBPS/Styles/style.css", StyleCSS, zip.Deflate)
	if err != nil {
		return err
	}

	return nil
}

// func addFileToZip(zipWriter *zip.Writer, filename string, relPath string, method uint16) error {
// 	file, err := os.Open(filename)
// 	if err != nil {
// 		return err
// 	}
// 	defer file.Close()

// 	info, err := file.Stat()
// 	if err != nil {
// 		return err
// 	}

// 	header, err := zip.FileInfoHeader(info)
// 	if err != nil {
// 		return err
// 	}
// 	header.Name = relPath
// 	header.Method = method

// 	writer, err := zipWriter.CreateHeader(header)
// 	if err != nil {
// 		return err
// 	}

// 	_, err = io.Copy(writer, file)
// 	return err
// }

func addStringToZip(zipWriter *zip.Writer, relPath, content string, method uint16) error {
	header := &zip.FileHeader{
		Name:   relPath,
		Method: method,
	}
	writer, err := zipWriter.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = writer.Write([]byte(content))
	return err
}

func addDirContentToZip(zipWriter *zip.Writer, dirPath string, method uint16) error {
	return filepath.Walk(dirPath, func(filePath string, info os.FileInfo, err error) error {
		if filepath.Base(filePath) == "volume.json" {
			return nil
		}
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}

		relPath, err := filepath.Rel(dirPath, filePath)
		if err != nil {
			return err
		}

		file, err := os.Open(filePath)
		if err != nil {
			return err
		}
		defer file.Close()

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}
		header.Name = relPath
		header.Method = method

		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}

		_, err = io.Copy(writer, file)
		return err
	})
}
