package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"gopkg.in/ini.v1"
)

func getRequest(url string, client *http.Client) ([]byte, error) {
	response, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func makeGETRequestAndProcessData(url string, client *http.Client, storeNo string, setURLTemplate string) {
	responseData, err := getRequest(url, client)
	if err != nil {
		fmt.Printf("发送GET请求失败: %v\n", err)
		return
	}

	fmt.Println(string(responseData))

	slice := strings.Split(string(responseData), ",")

	for _, publicIPURL := range slice {
		fmt.Println(publicIPURL)
		publicIPURL = "https://" + publicIPURL + "/"
		publicIPResponse, err := getRequest(publicIPURL, client)
		if err != nil {
			fmt.Printf("发送GET请求失败: %v\n", err)
			continue
		}

		parsedIP := net.ParseIP(string(publicIPResponse))
		if parsedIP != nil {
			fmt.Printf("%s 有效的IP地址\n", publicIPResponse)

			setURL := fmt.Sprintf(setURLTemplate, publicIPResponse, storeNo)
			fmt.Printf("%s\n", setURL)
			publicIPSendResponse, err := getRequest(setURL, client)
			if err != nil {
				fmt.Printf("发送GET请求失败: %v\n", err)
				continue
			}
			fmt.Printf("发送Get请求返回状态: %s\n", string(publicIPSendResponse))
			// 成功时候跳出循环
			break
		}
	}
}

const (
	DAEMON  = "d"
	FOREVER = "f"
)

func StripSlice(slice []string, element string) []string {
	for i := 0; i < len(slice); {
		if slice[i] == element && i != len(slice)-1 {
			slice = append(slice[:i], slice[i+1:]...)
		} else if slice[i] == element && i == len(slice)-1 {
			slice = slice[:i]
		} else {
			i++
		}
	}
	return slice
}

func SubProcess(args []string) *exec.Cmd {
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, "[-] Error: %s\n", err)
	}
	return cmd
}

func get_ini() string {
	exePath, err := os.Executable()
	if err != nil {
		fmt.Println("无法获取可执行文件路径：", err)
		return ""
	}

	exeDir := filepath.Dir(exePath)
	exeDir = filepath.Join(exeDir, "public_ip.ini")
	fmt.Println(exeDir)

	return exeDir
}

func main() {

	var version = "1.0.0"

	// 获取当前可执行文件的路径
	INI_FILE := get_ini()
	_, err := os.Stat(INI_FILE)
	if os.IsNotExist(err) {
		fmt.Println("配置文件不存在")
		os.Exit(0)
	}

	// 读取配置文件
	cfgs, err := ini.Load(INI_FILE)
	if err != nil {
		fmt.Println(err)
	}

	Get_Find_Ip_Url := cfgs.Section("global").Key("Get_Find_Ip_Url").Value()
	SedIpURL := cfgs.Section("global").Key("SedIpURL").Value()
	StoreNo := cfgs.Section("global").Key("StoreNo").Value()
	While_Time, _ := cfgs.Section("global").Key("While_Time").Int()

	daemon := flag.Bool(DAEMON, false, "run in daemon")
	forever := flag.Bool(FOREVER, false, "run in forever")
	showVersion := flag.Bool("h", false, "打印应用程序信息")
	showVersion_long := flag.Bool("help", false, "打印应用程序信息")
	flag.Parse()

	if *showVersion || *showVersion_long {
		fmt.Println("			Public_Ip ")
		fmt.Println("	Obtain the public network IP of the LAN terminal and send it to a specific interface")
		fmt.Println("Version:", version)
		fmt.Printf("Author:%s\n", "aixiao@aixiao.me")
		fmt.Println("")
		os.Exit(0)
	} else {
		fmt.Println("其他逻辑...")
	}

	if *daemon {
		SubProcess(StripSlice(os.Args, "-"+DAEMON))
		fmt.Printf("[*] Daemon running in PID: %d PPID: %d\n", os.Getpid(), os.Getppid())
		os.Exit(0)
	} else if *forever {
		for {
			cmd := SubProcess(StripSlice(os.Args, "-"+FOREVER))
			fmt.Printf("[*] Forever running in PID: %d PPID: %d\n", os.Getpid(), os.Getppid())
			time.Sleep(time.Second * 5)
			cmd.Wait()
		}
	} else {
		fmt.Printf("[*] Service running in PID: %d PPID: %d\n", os.Getpid(), os.Getppid())
	}

	// 把自己加入注册表，开机自启
	if runtime.GOOS == "windows" {
		regedit()
	}

	// 主函数
	for {
		client := &http.Client{
			Timeout: 5 * time.Second,
		}

		makeGETRequestAndProcessData(Get_Find_Ip_Url, client, StoreNo, SedIpURL)
		time.Sleep(time.Second * time.Duration(While_Time))
	}
}
