// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package apiGatewayConfDeploy

import (
	"net/http"

	"bytes"
	"encoding/json"
	"github.com/apid/apid-core/util"
	"github.com/gorilla/mux"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io"
	mathrand "math/rand"
	"strings"
	"sync/atomic"
	"time"
)

const (
	bundleTestUrl       = "http://127.0.0.1:9000"
	dummySignedEndpoint = "/dummyblob/{blobId}"
)

var _ = Describe("api", func() {
	var testCount int
	var testBundleMan *bundleManager
	var dummyDbMan *dummyDbManager
	var dummyApiMan *dummyApiManager
	var blobServer *dummyBlobServer

	var _ = BeforeEach(func() {
		testCount += 1
		concurrentDownloads := 5
		downloadQueueSize := 5

		// init test blob server
		if blobServer == nil {
			blobServer = &dummyBlobServer{
				serverEndpoint: blobStoreUri,
				signedEndpoint: dummySignedEndpoint,
				signedTimeout:  new(int32),
				blobTimeout:    new(int32),
				resetTimeout:   true,
			}
			blobServer.start()
		}

		// init dummy db manager
		dummyDbMan = &dummyDbManager{
			fileResponse: make(chan string),
		}

		// init dummy api manager
		dummyApiMan = &dummyApiManager{
			notifyChan: make(chan int, 1),
			initCalled: make(chan bool),
		}

		// init bundle manager
		testBundleMan = &bundleManager{
			blobServerUrl:         bundleTestUrl,
			dbMan:                 dummyDbMan,
			apiMan:                dummyApiMan,
			concurrentDownloads:   concurrentDownloads,
			markConfigFailedAfter: 5 * time.Second,
			bundleRetryDelay:      time.Second,
			bundleCleanupDelay:    5 * time.Second,
			downloadQueue:         make(chan *DownloadRequest, downloadQueueSize),
			isClosed:              new(int32),
			client: &http.Client{
				Timeout: time.Second,
				Transport: &http.Transport{
					MaxIdleConnsPerHost: 10,
				},
			},
		}
		testBundleMan.initializeBundleDownloading()
		time.Sleep(100 * time.Millisecond)
	})

	var _ = AfterEach(func() {
		testBundleMan.Close()
		testBundleMan = nil
		dummyDbMan = nil
		dummyApiMan = nil
	})

	Context("download blobs", func() {

		It("should download blob according to id", func() {
			// download blob
			id := util.GenerateUUID()
			testBundleMan.enqueueRequest(testBundleMan.makeDownloadRequest(id, nil))
			received := <-dummyDbMan.fileResponse
			Expect(received).Should(Equal(id))
		})

		It("should timeout connection and retry", func() {
			// setup timeout
			atomic.StoreInt32(blobServer.signedTimeout, 1)
			atomic.StoreInt32(blobServer.blobTimeout, 1)
			testBundleMan.client.Timeout = 500 * time.Millisecond
			testBundleMan.bundleRetryDelay = 50 * time.Millisecond

			// download blobs
			id := util.GenerateUUID()
			testBundleMan.enqueueRequest(testBundleMan.makeDownloadRequest(id, nil))
			received := <-dummyDbMan.fileResponse
			Expect(received).Should(Equal(id))

		}, 4)

		It("should mark as failure according to markConfigFailedAfter", func() {
			// setup timeout
			atomic.StoreInt32(blobServer.signedTimeout, 1)
			atomic.StoreInt32(blobServer.blobTimeout, 1)
			testBundleMan.client.Timeout = 100 * time.Millisecond
			testBundleMan.bundleRetryDelay = 100 * time.Millisecond
			testBundleMan.markConfigFailedAfter = 200 * time.Millisecond

			// download blobs
			id := util.GenerateUUID()
			req := testBundleMan.makeDownloadRequest(id, nil)
			Expect(req.markFailedAt.After(time.Now())).Should(BeTrue())
			testBundleMan.enqueueRequest(req)

			// should fail
			time.Sleep(time.Second)
			Expect(req.markFailedAt.IsZero()).Should(BeTrue())
		}, 4)
	})

	Context("download blobs for changelist", func() {
		It("should download blobs for changelist", func() {
			//setup test data
			count := mathrand.Intn(10) + 1
			configs := make([]*Configuration, count)
			for i := 0; i < count; i++ {
				conf := makeTestDeployment()
				conf.BlobID = util.GenerateUUID()
				conf.BlobResourceID = util.GenerateUUID()
				configs[i] = conf
			}

			// should download blobs for changelist
			testBundleMan.downloadBlobsWithCallback(extractBlobsToDownload(configs), dummyApiMan.notifyNewChange)
			for i := 0; i < 2*count; i++ {
				<-dummyDbMan.fileResponse
			}

			// should notify after 1st download attempt
			<-dummyApiMan.notifyChan
		})

		It("should notify after 1st download attempt unless failure", func() {
			//setup test data
			count := mathrand.Intn(10) + 1
			configs := make([]*Configuration, count)
			for i := 0; i < count; i++ {
				conf := makeTestDeployment()
				conf.BlobID = util.GenerateUUID()
				conf.BlobResourceID = util.GenerateUUID()
				configs[i] = conf
			}

			// setup timeout
			atomic.StoreInt32(blobServer.signedTimeout, 1)
			atomic.StoreInt32(blobServer.blobTimeout, 1)
			testBundleMan.client.Timeout = 500 * time.Millisecond
			testBundleMan.bundleRetryDelay = 50 * time.Millisecond

			// should download blobs for changelist
			testBundleMan.downloadBlobsWithCallback(extractBlobsToDownload(configs), dummyApiMan.notifyNewChange)

			// should notify after 1st download attempt
			<-dummyApiMan.notifyChan

			//should retry download
			for i := 0; i < 2*count; i++ {
				<-dummyDbMan.fileResponse
			}
		})

	})

})

type dummyApiManager struct {
	initCalled chan bool
	notifyChan chan int
}

func (a *dummyApiManager) InitAPI() {
	go func() {
		a.initCalled <- true
	}()
}

func (a *dummyApiManager) notifyNewChange() {
	a.notifyChan <- 1
}

type dummyBlobServer struct {
	serverEndpoint string
	signedEndpoint string
	signedTimeout  *int32
	blobTimeout    *int32
	resetTimeout   bool
}

func (b *dummyBlobServer) start() {
	services.API().HandleFunc(b.serverEndpoint, b.returnSigned).Methods("GET")
	services.API().HandleFunc(b.signedEndpoint, b.returnBlob).Methods("GET")
}

// send a dummy uri as response
func (b *dummyBlobServer) returnSigned(w http.ResponseWriter, r *http.Request) {
	defer GinkgoRecover()
	if atomic.LoadInt32(b.signedTimeout) == int32(1) {
		if b.resetTimeout {
			atomic.StoreInt32(b.signedTimeout, 0)
		}
		time.Sleep(time.Second)
	}
	vars := mux.Vars(r)
	blobId := vars["blobId"]

	uriString := strings.Replace(bundleTestUrl+b.signedEndpoint, "{blobId}", blobId, 1)
	log.Debug("dummyBlobServer returnSigned: " + uriString)

	res := blobServerResponse{
		Id:                       blobId,
		Kind:                     "Blob",
		Self:                     r.RequestURI,
		SignedUrl:                uriString,
		SignedUrlExpiryTimestamp: time.Now().Add(3 * time.Hour).Format(time.RFC3339),
	}

	resBytes, err := json.Marshal(res)
	Expect(err).Should(Succeed())
	_, err = io.Copy(w, bytes.NewReader(resBytes))
	Expect(err).Should(Succeed())
	w.Header().Set("Content-Type", headerSteam)
}

// send blobId back as response
func (b *dummyBlobServer) returnBlob(w http.ResponseWriter, r *http.Request) {
	defer GinkgoRecover()
	if atomic.LoadInt32(b.blobTimeout) == int32(1) {
		if b.resetTimeout {
			atomic.StoreInt32(b.blobTimeout, 0)
		}
		time.Sleep(time.Second)
	}
	vars := mux.Vars(r)
	blobId := vars["blobId"]
	log.Debug("dummyBlobServer returnBlob id=" + blobId)
	_, err := io.Copy(w, bytes.NewReader([]byte(blobId)))
	Expect(err).Should(Succeed())
	w.Header().Set("Content-Type", headerSteam)
}
