package request

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/docker/docker/api"
	dclient "github.com/docker/docker/client"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/ioutils"
	"github.com/docker/go-connections/sockets"
	"github.com/docker/go-connections/tlsconfig"
	"github.com/pkg/errors"
)

// Method creates a modifier that sets the specified string as the request method
func Method(method string) func(*http.Request) error {
	return func(req *http.Request) error {
		req.Method = method
		return nil
	}
}

// RawString sets the specified string as body for the request
func RawString(content string) func(*http.Request) error {
	return RawContent(ioutil.NopCloser(strings.NewReader(content)))
}

// RawContent sets the specified reader as body for the request
func RawContent(reader io.ReadCloser) func(*http.Request) error {
	return func(req *http.Request) error {
		req.Body = reader
		return nil
	}
}

// ContentType sets the specified Content-Type request header
func ContentType(contentType string) func(*http.Request) error {
	return func(req *http.Request) error {
		req.Header.Set("Content-Type", contentType)
		return nil
	}
}

// JSON sets the Content-Type request header to json
func JSON(req *http.Request) error {
	return ContentType("application/json")(req)
}

// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
// the Content-Type header of the request.
func JSONBody(data interface{}) func(*http.Request) error {
	return func(req *http.Request) error {
		jsonData := bytes.NewBuffer(nil)
		if err := json.NewEncoder(jsonData).Encode(data); err != nil {
			return err
		}
		req.Body = ioutil.NopCloser(jsonData)
		req.Header.Set("Content-Type", "application/json")
		return nil
	}
}

// Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers
func Post(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
	return Do(endpoint, append(modifiers, Method(http.MethodPost))...)
}

// Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers
func Delete(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
	return Do(endpoint, append(modifiers, Method(http.MethodDelete))...)
}

// Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers
func Get(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
	return Do(endpoint, modifiers...)
}

// Do creates and execute a request on the specified endpoint, with the specified request modifiers
func Do(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
	return DoOnHost(DaemonHost(), endpoint, modifiers...)
}

// DoOnHost creates and execute a request on the specified host and endpoint, with the specified request modifiers
func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
	req, err := New(host, endpoint, modifiers...)
	if err != nil {
		return nil, nil, err
	}
	client, err := NewHTTPClient(host)
	if err != nil {
		return nil, nil, err
	}
	resp, err := client.Do(req)
	var body io.ReadCloser
	if resp != nil {
		body = ioutils.NewReadCloserWrapper(resp.Body, func() error {
			defer resp.Body.Close()
			return nil
		})
	}
	return resp, body, err
}

// New creates a new http Request to the specified host and endpoint, with the specified request modifiers
func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Request, error) {
	_, addr, _, err := dclient.ParseHost(host)
	if err != nil {
		return nil, err
	}
	if err != nil {
		return nil, errors.Wrapf(err, "could not parse url %q", host)
	}
	req, err := http.NewRequest("GET", endpoint, nil)
	if err != nil {
		return nil, fmt.Errorf("could not create new request: %v", err)
	}

	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
		req.URL.Scheme = "https"
	} else {
		req.URL.Scheme = "http"
	}
	req.URL.Host = addr

	for _, config := range modifiers {
		if err := config(req); err != nil {
			return nil, err
		}
	}
	return req, nil
}

// NewHTTPClient creates an http client for the specific host
func NewHTTPClient(host string) (*http.Client, error) {
	// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
	proto, addr, _, err := dclient.ParseHost(host)
	if err != nil {
		return nil, err
	}
	transport := new(http.Transport)
	if proto == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
		// Setup the socket TLS configuration.
		tlsConfig, err := getTLSConfig()
		if err != nil {
			return nil, err
		}
		transport = &http.Transport{TLSClientConfig: tlsConfig}
	}
	transport.DisableKeepAlives = true
	err = sockets.ConfigureTransport(transport, proto, addr)
	return &http.Client{
		Transport: transport,
	}, err
}

// NewClient returns a new Docker API client
func NewClient() (dclient.APIClient, error) {
	return NewClientForHost(DaemonHost())
}

// NewClientForHost returns a Docker API client for the host
func NewClientForHost(host string) (dclient.APIClient, error) {
	httpClient, err := NewHTTPClient(host)
	if err != nil {
		return nil, err
	}
	return dclient.NewClient(host, api.DefaultVersion, httpClient, nil)
}

// FIXME(vdemeester) httputil.ClientConn is deprecated, use http.Client instead (closer to actual client)
// Deprecated: Use New instead of NewRequestClient
// Deprecated: use request.Do (or Get, Delete, Post) instead
func newRequestClient(method, endpoint string, data io.Reader, ct, daemon string, modifiers ...func(*http.Request)) (*http.Request, *httputil.ClientConn, error) {
	c, err := SockConn(time.Duration(10*time.Second), daemon)
	if err != nil {
		return nil, nil, fmt.Errorf("could not dial docker daemon: %v", err)
	}

	client := httputil.NewClientConn(c, nil)

	req, err := http.NewRequest(method, endpoint, data)
	if err != nil {
		client.Close()
		return nil, nil, fmt.Errorf("could not create new request: %v", err)
	}

	for _, opt := range modifiers {
		opt(req)
	}

	if ct != "" {
		req.Header.Set("Content-Type", ct)
	}
	return req, client, nil
}

// SockRequest create a request against the specified host (with method, endpoint and other request modifier) and
// returns the status code, and the content as an byte slice
// Deprecated: use request.Do instead
func SockRequest(method, endpoint string, data interface{}, daemon string, modifiers ...func(*http.Request)) (int, []byte, error) {
	jsonData := bytes.NewBuffer(nil)
	if err := json.NewEncoder(jsonData).Encode(data); err != nil {
		return -1, nil, err
	}

	res, body, err := SockRequestRaw(method, endpoint, jsonData, "application/json", daemon, modifiers...)
	if err != nil {
		return -1, nil, err
	}
	b, err := ReadBody(body)
	return res.StatusCode, b, err
}

// ReadBody read the specified ReadCloser content and returns it
func ReadBody(b io.ReadCloser) ([]byte, error) {
	defer b.Close()
	return ioutil.ReadAll(b)
}

// SockRequestRaw create a request against the specified host (with method, endpoint and other request modifier) and
// returns the http response, the output as a io.ReadCloser
// Deprecated: use request.Do (or Get, Delete, Post) instead
func SockRequestRaw(method, endpoint string, data io.Reader, ct, daemon string, modifiers ...func(*http.Request)) (*http.Response, io.ReadCloser, error) {
	req, client, err := newRequestClient(method, endpoint, data, ct, daemon, modifiers...)
	if err != nil {
		return nil, nil, err
	}

	resp, err := client.Do(req)
	if err != nil {
		client.Close()
		return resp, nil, err
	}
	body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
		defer resp.Body.Close()
		return client.Close()
	})

	return resp, body, err
}

// SockRequestHijack creates a connection to specified host (with method, contenttype, …) and returns a hijacked connection
// and the output as a `bufio.Reader`
func SockRequestHijack(method, endpoint string, data io.Reader, ct string, daemon string, modifiers ...func(*http.Request)) (net.Conn, *bufio.Reader, error) {
	req, client, err := newRequestClient(method, endpoint, data, ct, daemon, modifiers...)
	if err != nil {
		return nil, nil, err
	}

	client.Do(req)
	conn, br := client.Hijack()
	return conn, br, nil
}

// SockConn opens a connection on the specified socket
func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
	daemonURL, err := url.Parse(daemon)
	if err != nil {
		return nil, errors.Wrapf(err, "could not parse url %q", daemon)
	}

	var c net.Conn
	switch daemonURL.Scheme {
	case "npipe":
		return npipeDial(daemonURL.Path, timeout)
	case "unix":
		return net.DialTimeout(daemonURL.Scheme, daemonURL.Path, timeout)
	case "tcp":
		if os.Getenv("DOCKER_TLS_VERIFY") != "" {
			// Setup the socket TLS configuration.
			tlsConfig, err := getTLSConfig()
			if err != nil {
				return nil, err
			}
			dialer := &net.Dialer{Timeout: timeout}
			return tls.DialWithDialer(dialer, daemonURL.Scheme, daemonURL.Host, tlsConfig)
		}
		return net.DialTimeout(daemonURL.Scheme, daemonURL.Host, timeout)
	default:
		return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon)
	}
}

func getTLSConfig() (*tls.Config, error) {
	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")

	if dockerCertPath == "" {
		return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
	}

	option := &tlsconfig.Options{
		CAFile:   filepath.Join(dockerCertPath, "ca.pem"),
		CertFile: filepath.Join(dockerCertPath, "cert.pem"),
		KeyFile:  filepath.Join(dockerCertPath, "key.pem"),
	}
	tlsConfig, err := tlsconfig.Client(*option)
	if err != nil {
		return nil, err
	}

	return tlsConfig, nil
}

// DaemonHost return the daemon host string for this test execution
func DaemonHost() string {
	daemonURLStr := "unix://" + opts.DefaultUnixSocket
	if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
		daemonURLStr = daemonHostVar
	}
	return daemonURLStr
}

// NewEnvClientWithVersion returns a docker client with a specified version.
// See: github.com/docker/docker/client `NewEnvClient()`
func NewEnvClientWithVersion(version string) (*dclient.Client, error) {
	if version == "" {
		return nil, errors.New("version not specified")
	}

	var httpClient *http.Client
	if os.Getenv("DOCKER_CERT_PATH") != "" {
		tlsConfig, err := getTLSConfig()
		if err != nil {
			return nil, err
		}
		httpClient = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: tlsConfig,
			},
		}
	}

	host := os.Getenv("DOCKER_HOST")
	if host == "" {
		host = dclient.DefaultDockerHost
	}

	cli, err := dclient.NewClient(host, version, httpClient, nil)
	if err != nil {
		return cli, err
	}
	return cli, nil
}
