package main

import (
  "flag"
  "fmt"
  "log"
  "net"
  "net/http"
  "os"
  "os/signal"
  "syscall"
  "time"
  
  ratelimitkit "github.com/go-kit/kit/ratelimit"

  "github.com/juju/ratelimit"
  "github.com/matryer/goblueprints/chapter10/vault"
  "github.com/matryer/goblueprints/chapter10/vault/pb"
  "golang.org/x/net/context"
  "google.golang.org/grpc"
)

func main() {
  var (
    httpAddr = flag.String("http", ":8080", "numer portu dla protokołu http")
    gRPCAddr = flag.String("grpc", ":8081", "numer portu dla protokołu gRPC")
  )
  flag.Parse()
  ctx := context.Background()
  srv := vault.NewService()
  errChan := make(chan error)
  go func() {
    c := make(chan os.Signal, 1)
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
    errChan <- fmt.Errorf("%s", <-c)
  }()

  rlbucket := ratelimit.NewBucket(1*time.Second, 5)
  hashEndpoint := vault.MakeHashEndpoint(srv)
  {
    hashEndpoint = ratelimitkit.NewTokenBucketThrottler(rlbucket, time.Sleep)(hashEndpoint)
  }
  validateEndpoint := vault.MakeValidateEndpoint(srv)
  {
    validateEndpoint = ratelimitkit.NewTokenBucketThrottler(rlbucket, time.Sleep)(validateEndpoint)
  }

  endpoints := vault.Endpoints{
    HashEndpoint:     hashEndpoint,
    ValidateEndpoint: validateEndpoint,
  }

  // protokół HTTP
  go func() {
    log.Println("http:", *httpAddr)
    handler := vault.NewHTTPServer(ctx, endpoints)
    errChan <- http.ListenAndServe(*httpAddr, handler)
  }()

  // protokół gRPC
  go func() {
    listener, err := net.Listen("tcp", *gRPCAddr)
    if err != nil {
      errChan <- err
      return
    }
    log.Println("grpc:", *gRPCAddr)
    handler := vault.NewGRPCServer(ctx, endpoints)
    gRPCServer := grpc.NewServer()
    pb.RegisterVaultServer(gRPCServer, handler)
    errChan <- gRPCServer.Serve(listener)
  }()

  log.Fatalln(<-errChan)
}
