<commit_before>package factomclient

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"github.com/FactomProject/FactomCode/factomapi"
	"github.com/FactomProject/FactomCode/factomchain/factoid"
	"github.com/FactomProject/FactomCode/factomwire"
	"github.com/FactomProject/FactomCode/notaryapi"
	"github.com/FactomProject/FactomCode/restapi"
	"github.com/FactomProject/FactomCode/wallet"
	"github.com/FactomProject/gocoding"
	"github.com/hoisie/web"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

var server = web.NewServer()

func serve_init() {
	server.Post(`/v1/submitentry/?`, handleSubmitEntry)
	server.Post(`/v1/submitchain/?`, handleSubmitChain)
	server.Post(`/v1/buycredit/?`, handleBuyCreditPost)
	server.Post(`/v1/creditbalance/?`, handleGetCreditBalancePost)
	server.Post(`/v1/addentry/?`, handleSubmitEntry2)       // Needs to be removed later??
	server.Post(`/v1/getfilelist/?`, handleGetFileListPost) // to be replaced by DHT
	server.Post(`/v1/getfile/?`, handleGetFilePost)         // to be replaced by DHT
	server.Post(`/v1/factoidtx/?`, handleFactoidTx)

	server.Get(`/v1/creditbalance/?`, handleGetCreditBalancePost)
	server.Get(`/v1/buycredit/?`, handleBuyCreditPost)

	server.Get(`/v1/dblocksbyrange/([^/]+)(?:/([^/]+))?`, handleDBlocksByRange)
	server.Get(`/v1/dblock/([^/]+)(?)`, handleDBlockByHash)
	server.Get(`/v1/eblock/([^/]+)(?)`, handleEBlockByHash)
	server.Get(`/v1/eblockbymr/([^/]+)(?)`, handleEBlockByMR)
	server.Get(`/v1/entry/([^/]+)(?)`, handleEntryByHash)
	server.Get(`/v1/factoidtx/?`, handleFactoidTx)

}

func handleSubmitEntry(ctx *web.Context) {
	// convert a json post to a factom.Entry then submit the entry to factom
	fmt.Fprintln(ctx, "Entry Submitted")

	switch ctx.Params["format"] {
	case "json":
		entry := new(notaryapi.Entry)
		reader := gocoding.ReadBytes([]byte(ctx.Params["entry"]))
		err := factomapi.SafeUnmarshal(reader, entry)
		if err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}

		if err := factomapi.CommitEntry(entry); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}

		time.Sleep(1 * time.Second)
		if err := factomapi.RevealEntry(entry); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}
		fmt.Fprintln(ctx, "Entry Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleSubmitEntry2(ctx *web.Context) {
	// convert a json post to a factom.Entry then submit the entry to factom
	fmt.Fprintln(ctx, "Entry Submitted")

	switch ctx.Params["format"] {
	case "json":
		j := []byte(ctx.Params["entry"])
		e := new(factomapi.Entry)
		e.UnmarshalJSON(j)
		if err := factomapi.CommitEntry2(e); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err)
		}
		time.Sleep(1 * time.Second)
		if err := factomapi.RevealEntry2(e); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err)
		}
		fmt.Fprintln(ctx, "Entry Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleSubmitChain(ctx *web.Context) {

	// convert a json post to a factomapi.Chain then submit the entry to factomapi
	switch ctx.Params["format"] {
	case "json":
		reader := gocoding.ReadBytes([]byte(ctx.Params["chain"]))
		c := new(notaryapi.EChain)
		factomapi.SafeUnmarshal(reader, c)

		c.GenerateIDFromName()
		if c.FirstEntry == nil {
			fmt.Fprintln(ctx,
				"The first entry is required for submitting the chain:")
			return
		} else {
			c.FirstEntry.ChainID = *c.ChainID
		}

		fmt.Println("c.ChainID:", c.ChainID.String())

		if err := factomapi.CommitChain(c); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the chain:", err)
		}

		time.Sleep(1 * time.Second) //?? do we need to queue them up and look for the confirmation

		if err := factomapi.RevealChain(c); err != nil {
			fmt.Println(err.Error())
			fmt.Fprintln(ctx,
				"there was a problem with submitting the chain:", err)
		}

		fmt.Fprintln(ctx, "Chain Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleBuyCreditPost(ctx *web.Context) {
	var httpcode int = 200
	buf := new(bytes.Buffer)

	defer func() {
		ctx.WriteHeader(httpcode)
		ctx.Write(buf.Bytes())
	}()

	var abortMessage, abortReturn string

	defer func() {
		if abortMessage != "" && abortReturn != "" {
			ctx.Header().Add("Location", fmt.Sprint("/failed?message=", abortMessage, "&return=", abortReturn))
			ctx.WriteHeader(303)
		}
	}()

	ecPubKey := new(notaryapi.Hash)
	if ctx.Params["to"] == "wallet" {
		ecPubKey.Bytes = (*wallet.ClientPublicKey().Key)[:]
	} else {
		ecPubKey.Bytes, _ = hex.DecodeString(ctx.Params["to"])
	}

	fmt.Println("handleBuyCreditPost using pubkey: ", ecPubKey, " requested", ctx.Params["to"])

	factoid, _ := strconv.ParseFloat(ctx.Params["value"], 10)
	value := uint64(factoid * 1000000000)
	err := factomapi.BuyEntryCredit(1, ecPubKey, nil, value, 0, nil)

	if err != nil {
		abortMessage = fmt.Sprint("An error occured while submitting the buycredit request: ", err.Error())
		return
	} else {
		fmt.Fprintln(ctx, "MsgGetCredit Submitted")
	}

}

func handleFactoidTx(ctx *web.Context) {
	n, err := strconv.ParseUint(ctx.Params["ammount"], 10, 32)
	if err != nil {
		fmt.Println(err)
	}
	amt := uint32(n)

	addr, _, err := factoid.DecodeAddress(ctx.Params["to"])
	if err != nil {
		fmt.Println(err)
	}
	
	genb := factoid.FactoidGenesis(factomwire.TestNet)
	outs := factoid.OutputsTx(&genb.Transactions[0])
	txm := factoid.NewTxFromOutputToAddr(
		genb.Transactions[0].Id(),
		outs,
		amt,
		factoid.AddressReveal(*wallet.ClientPublicKey().Key),
		addr)
	ds := wallet.DetachMarshalSign(txm.TxData)
	ss := factoid.NewSingleSignature(ds)
	factoid.AddSingleSigToTxMsg(txm, ss)
	wire := factoid.TxMsgToWire(txm)
	fmt.Println(wire)
}

func handleGetCreditBalancePost(ctx *web.Context) {
	var httpcode int = 200
	buf := new(bytes.Buffer)
<commit_msg>comments on serve.go<commit_after>package factomclient

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"github.com/FactomProject/FactomCode/factomapi"
	"github.com/FactomProject/FactomCode/factomchain/factoid"
	"github.com/FactomProject/FactomCode/factomwire"
	"github.com/FactomProject/FactomCode/notaryapi"
	"github.com/FactomProject/FactomCode/restapi"
	"github.com/FactomProject/FactomCode/wallet"
	"github.com/FactomProject/gocoding"
	"github.com/hoisie/web"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

var server = web.NewServer()

func serve_init() {
	server.Post(`/v1/submitentry/?`, handleSubmitEntry)
	server.Post(`/v1/submitchain/?`, handleSubmitChain)
	server.Post(`/v1/buycredit/?`, handleBuyCreditPost)
	server.Post(`/v1/creditbalance/?`, handleGetCreditBalancePost)
	server.Post(`/v1/addentry/?`, handleSubmitEntry2)       // Needs to be removed later??
	server.Post(`/v1/getfilelist/?`, handleGetFileListPost) // to be replaced by DHT
	server.Post(`/v1/getfile/?`, handleGetFilePost)         // to be replaced by DHT
	server.Post(`/v1/factoidtx/?`, handleFactoidTx)

	server.Get(`/v1/creditbalance/?`, handleGetCreditBalancePost)
	server.Get(`/v1/buycredit/?`, handleBuyCreditPost)

	server.Get(`/v1/dblocksbyrange/([^/]+)(?:/([^/]+))?`, handleDBlocksByRange)
	server.Get(`/v1/dblock/([^/]+)(?)`, handleDBlockByHash)
	server.Get(`/v1/eblock/([^/]+)(?)`, handleEBlockByHash)
	server.Get(`/v1/eblockbymr/([^/]+)(?)`, handleEBlockByMR)
	server.Get(`/v1/entry/([^/]+)(?)`, handleEntryByHash)
	server.Get(`/v1/factoidtx/?`, handleFactoidTx)

}

func handleSubmitEntry(ctx *web.Context) {
	// convert a json post to a factom.Entry then submit the entry to factom
	fmt.Fprintln(ctx, "Entry Submitted")

	switch ctx.Params["format"] {
	case "json":
		entry := new(notaryapi.Entry)
		reader := gocoding.ReadBytes([]byte(ctx.Params["entry"]))
		err := factomapi.SafeUnmarshal(reader, entry)
		if err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}

		if err := factomapi.CommitEntry(entry); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}

		time.Sleep(1 * time.Second)
		if err := factomapi.RevealEntry(entry); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err.Error())
		}
		fmt.Fprintln(ctx, "Entry Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleSubmitEntry2(ctx *web.Context) {
	// convert a json post to a factom.Entry then submit the entry to factom
	fmt.Fprintln(ctx, "Entry Submitted")

	switch ctx.Params["format"] {
	case "json":
		j := []byte(ctx.Params["entry"])
		e := new(factomapi.Entry)
		e.UnmarshalJSON(j)
		if err := factomapi.CommitEntry2(e); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err)
		}
		time.Sleep(1 * time.Second)
		if err := factomapi.RevealEntry2(e); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the entry:", err)
		}
		fmt.Fprintln(ctx, "Entry Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleSubmitChain(ctx *web.Context) {

	// convert a json post to a factomapi.Chain then submit the entry to factomapi
	switch ctx.Params["format"] {
	case "json":
		reader := gocoding.ReadBytes([]byte(ctx.Params["chain"]))
		c := new(notaryapi.EChain)
		factomapi.SafeUnmarshal(reader, c)

		c.GenerateIDFromName()
		if c.FirstEntry == nil {
			fmt.Fprintln(ctx,
				"The first entry is required for submitting the chain:")
			return
		} else {
			c.FirstEntry.ChainID = *c.ChainID
		}

		fmt.Println("c.ChainID:", c.ChainID.String())

		if err := factomapi.CommitChain(c); err != nil {
			fmt.Fprintln(ctx,
				"there was a problem with submitting the chain:", err)
		}

		time.Sleep(1 * time.Second) //?? do we need to queue them up and look for the confirmation

		if err := factomapi.RevealChain(c); err != nil {
			fmt.Println(err.Error())
			fmt.Fprintln(ctx,
				"there was a problem with submitting the chain:", err)
		}

		fmt.Fprintln(ctx, "Chain Submitted")
	default:
		ctx.WriteHeader(403)
	}
}

func handleBuyCreditPost(ctx *web.Context) {
	var httpcode int = 200
	buf := new(bytes.Buffer)

	defer func() {
		ctx.WriteHeader(httpcode)
		ctx.Write(buf.Bytes())
	}()

	var abortMessage, abortReturn string

	defer func() {
		if abortMessage != "" && abortReturn != "" {
			ctx.Header().Add("Location", fmt.Sprint("/failed?message=", abortMessage, "&return=", abortReturn))
			ctx.WriteHeader(303)
		}
	}()

	ecPubKey := new(notaryapi.Hash)
	if ctx.Params["to"] == "wallet" {
		ecPubKey.Bytes = (*wallet.ClientPublicKey().Key)[:]
	} else {
		ecPubKey.Bytes, _ = hex.DecodeString(ctx.Params["to"])
	}

	fmt.Println("handleBuyCreditPost using pubkey: ", ecPubKey, " requested", ctx.Params["to"])

	factoid, _ := strconv.ParseFloat(ctx.Params["value"], 10)
	value := uint64(factoid * 1000000000)
	err := factomapi.BuyEntryCredit(1, ecPubKey, nil, value, 0, nil)

	if err != nil {
		abortMessage = fmt.Sprint("An error occured while submitting the buycredit request: ", err.Error())
		return
	} else {
		fmt.Fprintln(ctx, "MsgGetCredit Submitted")
	}

}

func handleFactoidTx(ctx *web.Context) {
	n, err := strconv.ParseUint(ctx.Params["ammount"], 10, 32)
	if err != nil {
		fmt.Println(err)
	}
	amt := uint32(n)

	addr, _, err := factoid.DecodeAddress(ctx.Params["to"])
	if err != nil {
		fmt.Println(err)
	}
	
	// instead of genb we will have to read from the current confirmed factoid
	// state
	genb := factoid.FactoidGenesis(factomwire.TestNet)
	outs := factoid.OutputsTx(&genb.Transactions[0])
	txm := factoid.NewTxFromOutputToAddr(
		genb.Transactions[0].Id(),
		outs,
		amt,
		factoid.AddressReveal(*wallet.ClientPublicKey().Key),
		addr)
	ds := wallet.DetachMarshalSign(txm.TxData)
	ss := factoid.NewSingleSignature(ds)
	factoid.AddSingleSigToTxMsg(txm, ss)
	wire := factoid.TxMsgToWire(txm)
	fmt.Println(wire)
}

func handleGetCreditBalancePost(ctx *web.Context) {
	var httpcode int = 200
	buf := new(bytes.Buffer)

{'fraction_non_alphanumeric': 0.1605600737821749, 'fraction_numerical': 0.01089963947346357, 'mean_word_length': 4.344086021505376, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4784411', 'n_tokens_mistral': 4719, 'n_tokens_neox': 4296, 'n_words': 888}