package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/binary"
	"encoding/pem"
	"io/ioutil"
	"log"

	ipfsapi "github.com/ipfs/go-ipfs-api"
	"golang.org/x/crypto/ssh"
)

func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) {
	// Private Key generation
	privateKey, err := rsa.GenerateKey(rand.Reader, bitSize)
	if err != nil {
		return nil, err
	}

	// Validate Private Key
	err = privateKey.Validate()
	if err != nil {
		return nil, err
	}

	log.Println("Private Key generated")
	return privateKey, nil
}

func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte {
	// Get ASN.1 DER format
	privDER := x509.MarshalPKCS1PrivateKey(privateKey)

	// pem.Block
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privDER,
	}

	// Private key in PEM format
	privatePEM := pem.EncodeToMemory(&privBlock)

	return privatePEM
}

// parseDims extracts two uint32s from the provided buffer.
func parseDims(b []byte) (uint32, uint32) {
	w := binary.BigEndian.Uint32(b)
	h := binary.BigEndian.Uint32(b[4:])
	return w, h
}

const WebDir = "/hugo-website"

func main() {
	// shell := ipfsapi.NewShell("127.0.0.1:5001")

	// ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Hour))
	// _, err := shell.KeyGen(ctx, "website-index")
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// id, err := shell.Add(
	// 	strings.NewReader(
	// 		"<!DOCTYPE HTML>" +
	// 			"<html><body><h1>heeeeeeeyaa</h1></body></html>",
	// 	),
	// )
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// log.Println("added file by name " + id)

	// resp, err := shell.PublishWithDetails(id, "website/index.html", 24*365*10*time.Hour, time.Hour, true)
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// log.Println(resp.Name)

	// obj, err := shell.ObjectGet("QmbJSh4EQvxz6cD6NyZ92smxBYfwTU6zr6No5APjANZ92D")

	// if err != nil {
	// 	log.Fatal(err)
	// }

	// log.Println(obj.Links)

	// err = shell.FilesMkdir(ctx, WebDir)
	// if err!= nil {
	// 	log.Fatal(err)
	// }

	// shell.FilesLs(ctx context.Context, path string, options ...ipfsapi.FilesOpt)
	// stats, err := shell.FilesStat(ctx, WebDir)
	// if err != nil {
	// 	if ipfsErr, ok := err.(*ipfsapi.Error); ok {
	// 		log.Println("IPFS error code: ", ipfsErr.Code, ipfsErr.Command)

	// 	}

	// 	log.Fatal(err)
	// }

	// log.Println(stats)

	// Public key authentication is done by comparing
	// the public key of a received connection
	// with the entries in the authorized_keys file.
	authorizedKeysBytes, err := ioutil.ReadFile("/home/hugo/.ssh/authorized_keys")
	if err != nil {
		log.Fatalf("Failed to load authorized_keys, err: %v", err)
	}

	authorizedKeysMap := map[string]bool{}
	for len(authorizedKeysBytes) > 0 {
		pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
		if err != nil {
			log.Fatal(err)
		}

		authorizedKeysMap[string(pubKey.Marshal())] = true
		authorizedKeysBytes = rest
	}

	// shell :=
	filestore, err := NewIPFSFilestore(ipfsapi.NewShell("127.0.0.1:5001"), WebDir)
	if err != nil {
		log.Fatal(err)
	}

	server := &Sshd{
		AuthorizedKeysMap: authorizedKeysMap,
		Filestore:         filestore,
	}

	log.Fatal(server.Listen("0.0.0.0:2022"))
}
