package main

import (
	"context"
	"encoding/hex"
	"fmt"
	"sync"
	"time"

	pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
	"code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model"
	"github.com/golang/glog"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type pgp struct {
	pgpc pb.PGPEncryptorClient
}

func newPGP(pgpc pb.PGPEncryptorClient) (*pgp, error) {
	return &pgp{
		pgpc: pgpc,
	}, nil
}

func (p *pgp) Name() string {
	return "PGP"
}

func (p *pgp) NextRun(now time.Time, lastRun bool) time.Time {
	if lastRun {
		return now.Add(1 * time.Minute)
	}
	return now.Add(15 * time.Minute)
}

func (p *pgp) RunAll(ctx context.Context, m model.Model) error {
	keys, err := m.GetPGPKeysRequiringAttention(ctx)
	if err != nil {
		return fmt.Errorf("GetPGPKeysRequiringAttention: %v", err)
	}

	if len(keys) == 0 {
		return nil
	}

	s := make(chan struct{}, 20)
	errC := make(chan error, len(keys))
	knownC := make(chan *model.PeerPGPKey, len(keys))
	unknownC := make(chan *model.PeerPGPKey, len(keys))

	var wg sync.WaitGroup
	wg.Add(len(keys))

	for _, key := range keys {
		go func(k *model.PeerPGPKey) {
			s <- struct{}{}
			defer func() {
				wg.Done()
				<-s
			}()

			glog.Infof("PGP: Processing %v", *k)

			// HACK(q3k)
			if k.State == "known" {
				knownC <- k
				return
			}

			fp, err := hex.DecodeString(k.Fingerprint)
			if err != nil {
				errC <- fmt.Errorf("could not decode fingerprint %q: %v", k.Fingerprint, err)
				return
			}

			req := &pb.KeyInfoRequest{
				Fingerprint: fp,
				Caching:     pb.KeyInfoRequest_CACHING_FORCE_REMOTE,
			}

			_, err = p.pgpc.KeyInfo(ctx, req)
			s, ok := status.FromError(err)
			switch {
			case err == nil:
				knownC <- k
			case ok && s.Code() == codes.NotFound:
				unknownC <- k
			default:
				unknownC <- k
				errC <- err
			}
		}(key)
	}

	wg.Wait()
	close(errC)
	close(knownC)
	close(unknownC)

	pcr := []*model.PeerCheckResult{}

	positive := []string{}
	for p := range knownC {
		positive = append(positive, p.Fingerprint)
		pcr = append(pcr, &model.PeerCheckResult{
			PeerASN:   p.PeerASN,
			CheckName: "pgp",
			Time:      time.Now(),
			Status:    model.PeerCheckStatus_Okay,
		})
	}
	negative := []string{}
	for n := range unknownC {
		negative = append(negative, n.Fingerprint)
		pcr = append(pcr, &model.PeerCheckResult{
			PeerASN:   n.PeerASN,
			CheckName: "pgp",
			Time:      time.Now(),
			Status:    model.PeerCheckStatus_Failed,
			Message:   fmt.Sprintf("key %q not found on keyservers", n.Fingerprint),
		})
	}

	glog.Infof("%v, %v", positive, negative)

	if len(positive) > 0 || len(negative) > 0 {
		err := m.ValidatePGPKeys(ctx, positive, negative)
		if err != nil {
			return fmt.Errorf("ValidatePGPKeys(%v, %v): %v", positive, negative, err)
		}
	}

	if len(pcr) > 0 {
		err = m.SubmitPeerCheckResults(ctx, "pgp", pcr)
		if err != nil {
			return err
		}
	}

	errs := []error{}
	for err := range errC {
		errs = append(errs, err)
	}

	if len(errs) > 0 {
		glog.Errorf("Errors while processing keys: %v", errs)
		return fmt.Errorf("Errors ocurred while processing keys")
	}

	return nil

}
