package server

import (
	"time"
	"net/http"
	"context"
	"log"
)

const (
	defaultServerReadTimeout     = 3 * time.Second
	defaultServerWriteTimeout    = 35 * time.Second
	defaultServerShutdownTimeout = 10 * time.Second
)

// Server holds the main HTTP server. It's a standard net/http Server.
type Server struct {
	*http.Server
	ShutdownTimeout time.Duration
}

// New instantiates a new server.
func New(addr string, handler http.Handler, opts ...func(*Server)) *Server {
	s := &Server{
		Server: &http.Server{
			Addr:         addr,
			Handler:      handler,
			ReadTimeout:  defaultServerReadTimeout,
			WriteTimeout: defaultServerWriteTimeout,
		},
		ShutdownTimeout: defaultServerShutdownTimeout,
	}

	for _, f := range opts {
		f(s)
	}

	return s
}

// Start starts the server instance.
func (s *Server) Start() error {
	if err := s.ListenAndServe(); err != http.ErrServerClosed {
		return err
	}
	return nil
}

// Stop stops the server instance.
func (s *Server) Stop() error {
	ctx, cancel := context.WithTimeout(context.Background(), s.ShutdownTimeout)
	defer cancel()
	return s.Shutdown(ctx)
}

// WithErrorLog sets the error logger for a http server.
func WithErrorLog(logger *log.Logger) func(*Server) {
	return func(s *Server) {
		s.ErrorLog = logger
	}
}
