// Copyright (C) 2014-2018 Goodrain Co., Ltd.
// RAINBOND, Application Management Platform

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package util

import (
	"errors"
	"fmt"
	"net"
	"runtime"
	"strings"

	"os"

	"io/ioutil"

	"regexp"

	"github.com/sirupsen/logrus"
	"github.com/tidwall/gjson"
)

func Source(l *logrus.Entry) *logrus.Entry {
	_, file, line, ok := runtime.Caller(2)
	if !ok {
		file = "<???>"
		line = 1
	} else {
		slash := strings.LastIndex(file, "/")
		file = file[slash+1:]
	}
	return l.WithField("source", fmt.Sprintf("%s:%d", file, line))
}

//ExternalIP 获取本机ip
func ExternalIP() (net.IP, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			return ip, nil
		}
	}
	return nil, errors.New("are you connected to the network?")
}

//GetHostID 获取机器ID
func GetHostID(nodeIDFile string) (string, error) {
	_, err := os.Stat(nodeIDFile)
	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadFile(nodeIDFile)
	if err != nil {
		return "", err
	}
	info := strings.Split(strings.TrimSpace(string(body)), "=")
	if len(info) == 2 {
		return info[1], nil
	}
	return "", fmt.Errorf("Invalid host uuid from file")
}

var rex *regexp.Regexp

//Format 格式化处理监控数据
func Format(source map[string]gjson.Result) map[string]interface{} {
	defer func() {
		if r := recover(); r != nil {
			logrus.Warnf("error deal with source msg %v", source)
		}
	}()
	if rex == nil {
		var err error
		rex, err = regexp.Compile(`\d+\.\d{3,}`)
		if err != nil {
			logrus.Error("create regexp error.", err.Error())
			return nil
		}
	}

	var data = make(map[string]interface{})

	for k, v := range source {
		if rex.MatchString(v.String()) {
			d := strings.Split(v.String(), ".")
			data[k] = fmt.Sprintf("%s.%s", d[0], d[1][0:2])
		} else {
			data[k] = v.String()
		}
	}
	return data
}
