/**************************************************************************************
 *
 *     Project:    kvmstoreserver-tools
 *     File name:  client.go
 *     Version:    1.0.0
 *     Date:       2018-01-15
 *
 *     Autor:      Bogdanovic Theodor
 *     Contact:    t.bogdanovic@hotmail.com
 *
 *     License:    GPLv3
 *
 **************************************************************************************/
/**************************************************************************************
 * Copyright 2018 Bogdanovic Theodor
 *
 * This file is part of kvmstoreserver-tools.
 *
 * kvmstoreserver-tools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * kvmstoreserver-tools is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with kvmstoreserver-tools.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************************/
/**************************************************************************************
 *  Further explanations:  This source code is under the license specified by the
 *                         Autor above. Core components or other packages are still
 *                         in source code form, under the license specified by the
 *                         respective author.
 **************************************************************************************/

package client

import (
	"bytes"
	"fmt"
	"net/http"
	"strconv"
	"sync"
	"time"
)

//*****************************************************************************
//*
//*      Structure: Synchronizer
//*
//*****************************************************************************

// ParaController ...
type ParaController struct {
	Wg sync.WaitGroup
}

//*****************************************************************************
//*
//*      Structure: InjClient
//*
//*****************************************************************************

// InjClient ...
type InjClient struct {
	clientID int
	url      string
}

//******************** Methods ************************************************

// generateKeyName ...
func (slf *InjClient) generateKeyName() string {
	return "System_Name_" + strconv.Itoa(slf.clientID)
}

// GenerateRequest ...
func (slf *InjClient) generateRequest() *bytes.Reader {

	newName := slf.generateKeyName()

	newNbr := slf.clientID
	newVers := float64(slf.clientID) + 0.99999999
	newAct := slf.clientID%2 == 0
	newNull := "null"

	return bytes.NewReader([]byte(
		fmt.Sprintf(`{"system_name": "%v","system_number": %v,"system_version": %v,"system_active": %v,"system_null": %v}`,
			newName, newNbr, newVers, newAct, newNull),
	))
}

// StartRequest ...
func (slf *InjClient) StartRequest(syncer *ParaController) {

	defer func() {
		err := recover()
		if err != nil {
			fmt.Printf("(RECOVER) Worker ID: %v - failed: Reason -> [Program Error: %v]\n",
				slf.clientID, err)

			syncer.Wg.Add(-1)
		}
	}()

	client := &http.Client{Timeout: time.Second * 60}
	callURL := slf.url + "/add/" + slf.generateKeyName()

	req, _ := http.NewRequest("POST", callURL, slf.generateRequest())
	req.Header.Set("User-Agent", "Injection-Client-storeserver-1.0.0")
	req.Header.Set("Content-Type", "application/json")

	resp, err := client.Do(req)

	if err != nil {
		fmt.Printf("Worker ID: %v - failed: Reason -> [Connection Error -> (%v)]\n",
			slf.clientID, err)
		return
	}
	if resp.StatusCode != 201 {
		fmt.Printf("Worker ID: %v - failed: Reason -> [Status != 201 | (Received: %v)]\n",
			resp.StatusCode, slf.clientID)
		return
	}

	resp.Body.Close()
	syncer.Wg.Add(-1)
}

//*****************************************************************************
//*
//*      Public Functions
//*
//*****************************************************************************

// NewWorker ...
func NewWorker(clientID int, url string) *InjClient {
	return &InjClient{
		clientID: clientID,
		url:      url,
	}
}
