package xrp

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/big"
	"net/http"

	"github.com/pkg/errors"
)

type Xrp struct {
	serverUrl string
}

func New(serverUrl string) *Xrp {
	return &Xrp{
		serverUrl: serverUrl,
	}
}

func (this *Xrp) CreateWallet() (addr, seed string, err error) {
	resp, err := http.Get(this.serverUrl + "/wallet/create")
	if err != nil {
		return
	}
	wallet := make(map[string]string)

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
	}

	json.Unmarshal(body, &wallet)

	addr = wallet["addr"]
	seed = wallet["seed"]
	return
}

func (this *Xrp) GetBalance(addr string) (balance *big.Int, ownerCount int64, err error) {
	resp, err := http.Get(this.serverUrl + "/wallet/getBalance?address=" + addr)
	if err != nil {
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
	}

	s := struct {
		Balance    string
		OwnerCount int64
	}{}

	json.Unmarshal(body, &s)
	balance, _ = new(big.Int).SetString(s.Balance, 10)
	return balance, s.OwnerCount, err
}

func (this *Xrp) SendToWithDestinationTag(seed, toAddr string, amount *big.Int, dstTag int) (err error) {
	resp, err := http.Get(this.serverUrl + fmt.Sprintf("/wallet/send?fromSeed=%s&toAddr=%s&amount=%s&destTag=%d", seed, toAddr, amount.String(), dstTag))
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
	}

	return
}

func (this *Xrp) SendTo(seed, toAddr string, amount *big.Int) (err error) {
	resp, err := http.Get(this.serverUrl + fmt.Sprintf("/wallet/send?fromSeed=%s&toAddr=%s&amount=%s", seed, toAddr, amount.String()))
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
	}

	return
}

func (this *Xrp) GetTxFee(seed, toAddr string, amount *big.Int) (fee *big.Int, err error) {
	resp, err := http.Get(this.serverUrl + fmt.Sprintf("/wallet/getTxFee?fromSeed=%s&toAddr=%s&amount=%s", seed, toAddr, amount.String()))
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
		return
	}

	fee = big.NewInt(0)
	fee, _ = fee.SetString(string(body), 10)
	return
}

func (this *Xrp) GetReserve() (reserveBase *big.Int, reserveInc *big.Int, err error) {
	resp, err := http.Get(this.serverUrl + "/wallet/getReserve")
	if err != nil {
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
	}

	m := map[string]int64{}

	json.Unmarshal(body, &m)
	reserveBase = big.NewInt(m["reserve_base"])
	reserveBase.Mul(reserveBase, big.NewInt(1000000))
	reserveInc = big.NewInt(m["reserve_inc"])
	reserveInc.Mul(reserveInc, big.NewInt(1000000))
	return
}
