package zip

import (
	"archive/zip"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

type walkFile struct {
	Name    string
	Modtime time.Time
	Size    uint64
}

func ZipDir(strPath, strRootDir string, zipWrite *zip.Writer) error {
	fileList, err := ioutil.ReadDir(strPath)
	if err != nil {
		return err
	}
	for _, one := range fileList {
		if one.IsDir() {
			if err = ZipDir(filepath.Join(strPath, one.Name()), strRootDir, zipWrite); err != nil {
				return err
			}
		} else {
			if err = zipFile(filepath.Join(strPath, one.Name()), strRootDir, zipWrite); err != nil {
				return err
			}
		}
	}
	return nil
}
func zipFile(strPath, strRootDir string, zipWrite *zip.Writer) error {
	relPath, err := filepath.Rel(strRootDir, strPath)
	if err != nil {
		return err
	}
	fileStat, err := os.Stat(strPath)
	if err != nil {
		return err
	}
	fh, err := zip.FileInfoHeader(fileStat)
	if err != nil {
		return err
	}
	fh.Name = relPath
	//默认不压缩，所以要设置下
	fh.Method = zip.Deflate
	zw, err := zipWrite.CreateHeader(fh)
	if err != nil {
		return err
	}
	f, err := os.Open(strPath)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(zw, f)
	if err != nil {
		return err
	}

	return err
}
func unzipFile(file *zip.File, strFileName string) error {
	r, err := file.Open()
	if err != nil {
		log.Error("open", err)
		return err
	}
	defer r.Close()
	if err := os.MkdirAll(filepath.Dir(strFileName), os.ModePerm); err != nil {
		log.Error(err)
		return err
	}
	if err = func() error {
		out, err := os.Create(strFileName)
		if err != nil {
			log.Error("create", err)
			return err
		}
		defer out.Close()
		if _, err = io.Copy(out, r); err != nil {
			log.Error("copy", err)
			return err
		}
		return nil
	}(); err != nil {
		return err
	}
	if err = os.Chtimes(strFileName, time.Now(), file.ModTime()); err != nil {
		log.Error("settime", err)
		return err
	}
	return nil
}

func Unzip(zipFileName, strPath string) error {
	zipReader, err := zip.OpenReader(zipFileName)
	if err != nil {

		return err
	}
	defer zipReader.Close()
	for _, file := range zipReader.File {
		//zip文件中的路径斜杠需要转换

		if err = unzipFile(file, filepath.Join(strPath,
			filepath.Join(strings.Split(strings.Replace(
				file.Name, "\\", "/", -1), "/")...))); err != nil {
			return err
		}
	}
	return nil
}
func ZipDirectory(strSrcPath, strZipFileName string) (err error) {
	f, err := os.Create(strZipFileName)
	if err != nil {
		return
	}
	defer f.Close()
	zipW := zip.NewWriter(f)
	defer zipW.Close()

	err = ZipDir(strSrcPath, strSrcPath, zipW)
	return
}

//解压压缩包中指定名称的文件，如果找不到，则出错
func UnzipFile(zipFileName, fileName, outFileName string) error {
	zipReader, err := zip.OpenReader(zipFileName)
	if err != nil {

		return err
	}
	defer zipReader.Close()

	for _, file := range zipReader.File {
		if file.Name == fileName {

			if err = unzipFile(file, outFileName); err != nil {
				return err
			}
			return nil
		}
	}
	return fmt.Errorf("not found file:%s at the zip file.", fileName)
}
