package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"log/syslog"
	"net/http"
	"net/smtp"
	"os"
	"time"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

var _appversion string = "0.1"
var _appname string = "ZiCloud-API"
var URL string = "https://ipa-cl.zi-tel.com"

func audit(txt string) {

	syslogger, err := syslog.New(syslog.LOG_INFO, _appname)
	if err != nil {
		log.Fatalln(err)
	}
	log.SetOutput(syslogger)
	log.Println(txt)
}

var RealIP string
var secretKey = []byte("P*%!5+u!$y+cgM+P8bybzgnXpsd2Lv2z") // 32 bytes
func sendMail(str string, subject string, recipient string) {
	auth := smtp.PlainAuth("", "zicloud@zi-tel.com", "5Sd?^AQx@r2OGRvS?i|DO0", "mail.zi-tel.com")
	to := []string{recipient}
	buff := make([]byte, 8)
	rand.Read(buff)
	random_str := base64.StdEncoding.EncodeToString(buff)
	msg := []byte("To:" + recipient + "\r\n" +
		"Date: " + time.Now().Format(time.RFC1123) + "\r\n" +
		"Message-Id: <" + random_str + "@ZiCloud.com>" + "\r\n" +
		"subject: " + subject + "\r\n" +
		"From: ZiCloud <" + "zicloud@zi-tel.com" + ">\r\n" +
		str)
	err := smtp.SendMail("mail.zi-tel.com:25", auth, "zicloud@zi-tel.com", to, msg)
	if err != nil {
		log.Fatal(err)
	}
}
func extractIP(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		RealIP = c.RealIP()
		audit("Recieved request from: " + RealIP)
		return next(c)
	}
}
func main() {
	if len(os.Args) != 3 {
		fmt.Println("Wrong Usage:\n\t ./CMD IP Port")
		audit("Application in the wrong way")
		os.Exit(1)
	}
	echoHandler := echo.New()
	echoHandler.Use(extractIP)
	echoHandler.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*", "*"},
		AllowMethods: []string{http.MethodGet, http.MethodPost},
	}))
	audit("Application " + _appname + " (" + _appversion + ") Started by " + os.Getenv("USER"))
	echoHandler.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})

	h := &handler{}
	echoHandler.POST("/login", h.login)
	echoHandler.GET("/private", h.private, isLoggedIn)

	echoHandler.GET("/admin", h.private, isLoggedIn, isAdmin)
	echoHandler.POST("/addUser", h.addUser, isLoggedIn, isAdmin)
	echoHandler.POST("/disableUser", h.disableUser, isLoggedIn, isAdmin)
	echoHandler.POST("/resetUser", h.resetUser)
	echoHandler.GET("/verifyUser", h.verifyUser)
	echoHandler.POST("/dnsrecordadd", h.dnsrecordadd, isLoggedIn, isAdmin)
	echoHandler.POST("/token", h.token, isLoggedIn)
	echoHandler.Logger.Fatal(echoHandler.Start(os.Args[1] + ":" + os.Args[2]))
}
func encrypt(key []byte, text string) string {
	// key := []byte(keyText)
	plaintext := []byte(text)
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	// convert to base64
	return base64.URLEncoding.EncodeToString(ciphertext)
}
func decrypt(key []byte, cryptoText string) string {
	ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	if len(ciphertext) < aes.BlockSize {
		panic("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	// XORKeyStream can work in-place if the two arguments are the same.
	stream.XORKeyStream(ciphertext, ciphertext)

	return fmt.Sprintf("%s", ciphertext)
}

type _response struct {
	Message string `json:"message"`
	Origin  string `json:"origin"`
	Code    int    `json:"code"`
}
