package utils

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io"
	"netease_control_center/interfaces/log"
	"os"
	"path"
)

func FindFileByFileName(paths []string, fileName string) string {
	for _, p := range paths {
		if path.Base(p) == fileName {
			return p
		}
	}
	return ""
}

func CompressFiles(paths []string) []byte {
	buf := new(bytes.Buffer)
	w := zip.NewWriter(buf)
	for _, v := range paths {
		log.Println(log.DebugLog, "Path:", v)
		if fd, err := os.Open(v); err == nil {
			if f, err := w.Create(path.Base(v)); err == nil {
				io.Copy(f, fd)
			}
			fd.Close()
		} else {
			log.Println(log.DebugLog, "Open file err:", err)
		}
	}
	w.Close()

	fmt.Println(string(buf.String()))

	return buf.Bytes()
}

func CompressFilesToLocalFile(srcfiles []string, destfile string) error {
	os.Remove(destfile)
	fmt.Println(log.DebugLog, "Begin to compress file to ", destfile, " src files:", srcfiles)
	if fd, fderr := os.OpenFile(destfile, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0666); fderr == nil {
		zipwriter := zip.NewWriter(fd)
		for _, v := range srcfiles {
			if srcfd, srcfderr := os.Open(v); srcfderr == nil {
				if zipfd, zipfderr := zipwriter.Create(path.Base(v)); zipfderr == nil {
					if _, iocpyerr := io.Copy(zipfd, srcfd); iocpyerr != nil {
						log.Println(log.ErrorLog, "io cpy error!", iocpyerr)
					}
				} else {
					log.Println(log.ErrorLog, "create file in zip error!")
				}
				srcfd.Close()
			} else {
				log.Println(log.ErrorLog, "open src file error", v, srcfderr)
			}
		}

		zipwriter.Close()
		fd.Close()
		return nil
	} else {
		log.Println(log.DebugLog, "back up file error! open dest file error!", fderr)
		return fderr
	}
}

func UnCompressFileFromLocalFile(toRestoreFiles []string, localFile string) error {
	if fd, err := os.Open(localFile); err == nil {
		fdstat, _ := fd.Stat()
		if zipread, zipreaderr := zip.NewReader(fd, fdstat.Size()); zipreaderr == nil {
			for _, zipfiles := range zipread.File {
				if zipfilefd, zipfileerr := zipfiles.Open(); zipfileerr == nil {
					if pt := FindFileByFileName(toRestoreFiles, zipfiles.Name); pt != "" {
						if fd, err := os.OpenFile(pt, os.O_TRUNC|os.O_RDWR|os.O_CREATE|os.O_SYNC, os.ModePerm); err == nil {
							io.Copy(fd, zipfilefd)
							fd.Chmod(os.ModePerm)
							fd.Close()
							log.Println(log.DebugLog, "Copy file:", fd.Name())
						} else {
							log.Println(log.DebugLog, "Create fail:", pt, err)
						}
					}
					zipfilefd.Close()
				} else {
					log.Println(log.ErrorLog, "zip file open fail:", zipfileerr)
				}
			}

			return nil
		} else {
			log.Println(log.ErrorLog, "Read zip file error:", zipreaderr)
			return zipreaderr
		}
	} else {
		log.Println(log.ErrorLog, "Open local file error!", err)
		return err
	}
}

func UnCompressBuffer(data []byte, paths []string) {
	if rd, err := zip.NewReader(bytes.NewReader(data), int64(len(data))); err == nil {
		for _, rf := range rd.File {
			zipfilefd, zipfilefderr := rf.Open()
			if zipfilefderr != nil {
				log.Println(log.DebugLog, "zip file open, err:", zipfilefderr, " err:", rf.Name)
				continue
			}

			if pt := FindFileByFileName(paths, rf.Name); pt != "" {
				if fd, err := os.OpenFile(pt, os.O_TRUNC|os.O_RDWR|os.O_CREATE|os.O_SYNC, os.ModePerm); err == nil {
					io.Copy(fd, zipfilefd)
					fd.Chmod(os.ModePerm)
					fd.Close()
					log.Println(log.DebugLog, "Copy file:", fd.Name())
				} else {
					log.Println(log.DebugLog, "Create fail:", pt, err)
				}
			}

			zipfilefd.Close()
		}
	}
}
