package main

import (
	"fmt"
	//"math"
	"path/filepath"
	"log"
	"github.com/jlaffaye/ftp"
	"time"
	"bytes"
	"os"
	"io"
	"io/ioutil"
	"strconv"
	"encoding/json"
)

type FtpTransferInfo struct
{
	serverAddr string `json:"severAddr"`
	port int64 `json:"port"`
	id string `json:"id"`
	pw string `json:"pw"`
	remote string `json:"remote"`
	sourceDir string `json:"sourceDir"`
	fileFilter string `json:"fileFilter"`
	renameDir string `json:"renameDir"`
	logFileNameWithoutExtension string `json:"logFileNameWithoutExtension"`
}

func main() {
	//fmt.Println("Hello, World")
	// var x int = 5
	// var y int = 7

	// uptimeTicker := time.NewTicker(5 * time.Second)
	// dateTicker := time.NewTicker(10 * time.Second)

	fti, err := GetConfigInfo("./ftpConfig.json")
	CheckErr(err)

	transferTicker := time.NewTicker(30 * time.Second)
	for{
		select{
			// case <-uptimeTicker.C:
			// 	var sum int = x + y
			// 	fmt.Println(sum)
			// case <-dateTicker.C:
			// 	var sum int = x - y
			// 	fmt.Println(sum)

			case <-transferTicker.C:
				TransferFiles(fti)
		}
	}

	//TransferFiles()
}

func CheckErr(err error){
	if err != nil {
		log.Fatal(err)
	}
}

func GetConfigInfo(configFile string) (ftpTransferInfo FtpTransferInfo, err error){
	// Open our jsonFile
    jsonFile, err := os.Open(configFile)
    // if we os.Open returns an error then handle it
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("Successfully Opened " + configFile)
    // defer the closing of our jsonFile so that we can parse it later on
    defer jsonFile.Close()

    byteValue, _ := ioutil.ReadAll(jsonFile)

    // var ftpInfo map[FtpTransferInfo]interface{}
    // json.Unmarshal([]byte(byteValue), &ftpInfo)

    var ftpInfo FtpTransferInfo

    json.Unmarshal(byteValue, &ftpInfo)

    fmt.Println(ftpInfo.serverAddr)

	// ftpInfo := FtpTransferInfo{
	// 	serverAddr: "pdjj14.synology.me",
	// 	port: 21,
	// 	id: "pdjj14",
	// 	pw: "Hanjaejoong14!",
	// 	remote: "/home/temp",
	// 	sourceDir: ".\\",
	// 	fileFilter: "*.icp",
	// 	renameDir: "transferred\\",
	// 	logFileNameWithoutExtension: "log.txt"}

	return ftpInfo, nil
}

func TransferFiles(ftpTransferInfo FtpTransferInfo)(){
	files, err := filepath.Glob(ftpTransferInfo.fileFilter)
	CheckErr(err)

	c, err := ftp.Dial(ftpTransferInfo.serverAddr + ":" + strconv.FormatInt(ftpTransferInfo.port, 10), ftp.DialWithTimeout(5*time.Second))
	CheckErr(err)

	err = c.Login(ftpTransferInfo.id, ftpTransferInfo.pw)
	CheckErr(err)

	path, err := c.CurrentDir()
	CheckErr(err)

	fmt.Println(path);

	err = c.ChangeDir(ftpTransferInfo.remote)
	CheckErr(err)

	path, err = c.CurrentDir()
	CheckErr(err)

	fmt.Println(path);

	fo, err := os.OpenFile(ftpTransferInfo.logFileNameWithoutExtension, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0777)
	CheckErr(err)

	fmt.Fprintln(fo, "")
	fmt.Fprintln(fo, time.Now().String() + "> FTP Uploading is started.")

	for _, file := range files{
		data := bytes.NewBufferString(file)
		err = c.Stor(file, data)
		if err != nil {
			log.Fatal(err)
		} else {
			logMsg := time.Now().String() + "> Succeeded to upload file: " + file
			fmt.Println(logMsg)
			fmt.Fprintln(fo, logMsg, err)

			target := ftpTransferInfo.renameDir + file
			err = os.Rename(file, target)
			CheckErr(err)

			logMsg = time.Now().String() + "> Succeeded to move file: <source: " + file + ">, <target: " + target + ">"
			fmt.Println(logMsg)
			fmt.Fprintln(fo, logMsg, err)
		}
	}

	err = c.Quit()
	CheckErr(err)

	fmt.Fprintln(fo, time.Now().String() + "> FTP Uploading is terminiated.")
}

func MoveFile(source, target string) (err error) {
	in, err := os.Open(source)
    if err != nil {
        return err
    }

    defer in.Close()
    out, err := os.Create(target)
    if err != nil {
        return err
    }
    
    defer func() {
        cerr := out.Close()
        if err == nil {
            err = cerr
        }
    }()

    if _, err = io.Copy(out, in); err != nil {
        return err
    }
    err = out.Sync()
   
	err = os.Remove(source)
	if err != nil {
		return err
	}

	return err
}