//该程序用来版本更新
package main

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"time"

	ps "github.com/mitchellh/go-ps"
)

func main() {
	bys, err := ioutil.ReadFile("watch.json")
	if err != nil {
		log.Panic(err)
	}
	cfg := &config{}
	err = json.Unmarshal(bys, cfg)
	if err != nil {
		log.Panic(err)
	}
	if _, err = os.Stat(cfg.Dest); os.IsNotExist(err) {
		log.Panic(cfg.Dest, err)
	}
	if _, err = os.Stat(cfg.Src); os.IsNotExist(err) {
		log.Panic(cfg.Src, err)
	}
	if _, err = os.Stat(cfg.Run); os.IsNotExist(err) {
		log.Panic(cfg.Run, err)
	}
	for {
		//直到找不到这个run的进程
		for {
			bfound := false
			pl, err := ps.Processes()
			if err != nil {
				log.Panic(err)
			}
			for _, one := range pl {
				if filepath.Base(cfg.Run) == one.Executable() {
					bfound = true
					break
				}
			}
			if !bfound {
				break
			}
			time.Sleep(time.Second)
		}
		if err = updateDir(cfg.Dest, cfg.Src); err != nil {
			log.Panic(err)
		}
		cmd := exec.Command("cmd.exe", "/c", "start "+cfg.Run)
		if err = cmd.Run(); err != nil {
			log.Panic(err)
		}
	}
}

//复制src中的文件至dest中
func updateDir(dest, src string) error {
	return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
		//本目录不处理
		if path == src {
			return nil
		}
		destFile := filepath.Join(dest, path[len(src)+1:])
		if info.IsDir() {
			if _, e := os.Stat(destFile); os.IsNotExist(e) {
				log.Println("mkdir", destFile)
				return os.Mkdir(destFile, os.ModePerm)
			} else if e != nil {
				return e
			}
		} else {
			if destInfo, e := os.Stat(destFile); os.IsNotExist(e) {
				log.Println("copy", destFile, "->", path)
				if e = copyFile(destFile, path); e != nil {
					return e
				}
				if e = os.Chtimes(destFile, info.ModTime(), info.ModTime()); e != nil {
					return e
				}
			} else if e != nil {
				return e
			} else if destInfo.ModTime().Before(info.ModTime()) {
				log.Println("copy", destFile, "->", path)
				if e = copyFile(destFile, path); e != nil {
					return e
				}
				if e = os.Chtimes(destFile, info.ModTime(), info.ModTime()); e != nil {
					return e
				}
			}
		}

		return nil
	})
}
func copyFile(dest, src string) error {
	f, e := os.Create(dest)
	if e != nil {
		return e
	}
	defer f.Close()
	rf, e := os.Open(src)
	if e != nil {
		return e
	}
	defer rf.Close()
	if _, e = io.Copy(f, rf); e != nil {
		return e
	}
	return nil
}
