// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// HTTP reverse proxy handler

package http

import (
	"io"
	"log"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)

// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
type ReverseProxy struct {
	// Director must be a function which modifies
	// the request into a new request to be sent
	// using Transport. Its response is then copied
	// back to the original client unmodified.
	Director func(*Request)

	// The Transport used to perform proxy requests.
	// If nil, DefaultTransport is used.
	Transport RoundTripper

	// FlushInterval specifies the flush interval, in
	// nanoseconds, to flush to the client while
	// coping the response body.
	// If zero, no periodic flushing is done.
	FlushInterval int64
}

func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
func NewSingleHostReverseProxy(target *URL) *ReverseProxy {
	director := func(req *Request) {
		req.URL.Scheme = target.Scheme
		req.URL.Host = target.Host
		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
		if q := req.URL.RawQuery; q != "" {
			req.URL.RawPath = req.URL.Path + "?" + q
		} else {
			req.URL.RawPath = req.URL.Path
		}
		req.URL.RawQuery = target.RawQuery
	}
	return &ReverseProxy{Director: director}
}

func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) {
	transport := p.Transport
	if transport == nil {
		transport = DefaultTransport
	}

	outreq := new(Request)
	*outreq = *req // includes shallow copies of maps, but okay

	p.Director(outreq)
	outreq.Proto = "HTTP/1.1"
	outreq.ProtoMajor = 1
	outreq.ProtoMinor = 1
	outreq.Close = false

	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		outreq.Header.Set("X-Forwarded-For", clientIp)
	}

	res, err := transport.RoundTrip(outreq)
	if err != nil {
		log.Printf("http: proxy error: %v", err)
		rw.WriteHeader(StatusInternalServerError)
		return
	}

	hdr := rw.Header()
	for k, vv := range res.Header {
		for _, v := range vv {
			hdr.Add(k, v)
		}
	}

	rw.WriteHeader(res.StatusCode)

	if res.Body != nil {
		var dst io.Writer = rw
		if p.FlushInterval != 0 {
			if wf, ok := rw.(writeFlusher); ok {
				dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval}
			}
		}
		io.Copy(dst, res.Body)
	}
}

type writeFlusher interface {
	io.Writer
	Flusher
}

type maxLatencyWriter struct {
	dst     writeFlusher
	latency int64 // nanos

	lk   sync.Mutex // protects init of done, as well Write + Flush
	done chan bool
}

func (m *maxLatencyWriter) Write(p []byte) (n int, err os.Error) {
	m.lk.Lock()
	defer m.lk.Unlock()
	if m.done == nil {
		m.done = make(chan bool)
		go m.flushLoop()
	}
	n, err = m.dst.Write(p)
	if err != nil {
		m.done <- true
	}
	return
}

func (m *maxLatencyWriter) flushLoop() {
	t := time.NewTicker(m.latency)
	defer t.Stop()
	for {
		select {
		case <-t.C:
			m.lk.Lock()
			m.dst.Flush()
			m.lk.Unlock()
		case <-m.done:
			return
		}
	}
	panic("unreached")
}
