package rules

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"iwarma.ru/console/correlator/events"
	"os"
	"testing"
	"time"
)

func TestBashActionType(t *testing.T) {
	var action BashAction

	if action.GetType() != BashActionType {
		t.Errorf("Bad action type: %v", action.GetType())
	}
}

func TestBashToInterface(t *testing.T) {
	action := BashAction{Body: "ASSS"}

	i, err := action.ToInterface()
	if err != nil {
		t.Errorf("Can't serialize: %v", err)
	}

	m, ok := i["body"]
	if !ok {
		t.Errorf("No body")
	}

	if m != "ASSS" {
		t.Errorf("Bad body value: %v", err)
	}

}

func TestBashActionSerialize(t *testing.T) {
	action := BashAction{Body: "ASSS"}

	b, err := json.Marshal(action)
	if err != nil {
		t.Errorf("Can't serialize action: %v", err)
	}

	if string(b) != `{"body":"ASSS","type":"bash"}` {
		t.Errorf("Bad serialized action: %v", string(b))
	}
}

func TestBashActionDeserialize(t *testing.T) {

	var action BashAction

	err := json.Unmarshal([]byte(`{"body":"ASSS","type":"bash"}`), &action)
	if err != nil {
		t.Errorf("Can't read action: %v", err)
	}

	if action.Body != "ASSS" {
		t.Errorf("Bad action body: %v", action.Body)
	}
}

func TestBashActionDesirealizeError(t *testing.T) {
	var action BashAction

	err := json.Unmarshal([]byte(`{"body":"ASSS","type":"zzzz"}`), &action)
	if err == nil {
		t.Error("No error with bad action")
	}
}

func TestBashActionParseInterface(t *testing.T) {
	i := make(map[string]interface{})
	i["body"] = "ASS"
	i["type"] = BashActionType

	action := &BashAction{}

	err := action.ParseInterface(i)
	if err != nil {
		t.Errorf("Can't parse interface: %v", err)
	}

	if action.Body != "ASS" {
		t.Errorf("Bad action body: %v", action.Body)
	}
}

func TestBashActionParseInterfaceError1(t *testing.T) {
	var i interface{}

	action := &BashAction{}

	err := action.ParseInterface(i)
	if err == nil {
		t.Error("Can parse wrong interface type")
	}
}

func TestBashActionParseInterfaceError2(t *testing.T) {
	i := make(map[string]interface{})

	action := &BashAction{}

	err := action.ParseInterface(i)
	if err == nil {
		t.Error("Can parse wrong interface without body")
	}
}

func TestBashActionParseInterfaceError3(t *testing.T) {
	i := make(map[string]interface{})
	i["body"] = "ASS"

	action := &BashAction{}

	err := action.ParseInterface(i)
	if err == nil {
		t.Error("Can parse wrong interface without type")
	}
}

func TestBashActionParseInterfaceError4(t *testing.T) {
	i := make(map[string]interface{})
	i["body"] = "ASS"
	i["type"] = "ASS"

	action := &BashAction{}

	err := action.ParseInterface(i)
	if err == nil {
		t.Error("Can parse wrong interface with bad type")
	}
}

func TestBashActionPerform(t *testing.T) {

	tmpFile, err := ioutil.TempFile("", "test.*.test")
	if err != nil {
		t.Errorf("Can't create temp file: %v", err)
		return
	}
	err = tmpFile.Close()
	if err != nil {
		t.Errorf("Can't close temp file: %v", err)
	}
	defer os.Remove(tmpFile.Name())

	action := &BashAction{Body: `#!/bin/bash
NEW_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
echo "$NEW_UUID" > {{.app_name}}`}
	eventsArray := make([]*events.Event, 1)
	eventsArray[0] = &events.Event{
		events.FirstEvent: time.Now(),
		events.LastEvent:  time.Now(),
		events.EventCount: 5,
		"event_severity":  5,
		"app_name":        tmpFile.Name(),
	}

	err = action.Perform(&eventsArray)
	if err != nil {
		t.Errorf("Can't perform action: %v", err)
	}

	// Check script result
	file, err := os.Open(tmpFile.Name())
	if err != nil {
		t.Errorf("Can't open result file: %v", err)
	}

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		t.Errorf("Can't open result file: %v", err)
	}

	if len(string(buf)) == 0 {
		t.Error("Got empty result file")
	}
	
	t.Logf("Got result file content: \"%v\"", string(buf))
}

func TestBashActionPerform2(t *testing.T) {
	cur := time.Now().Unix()
	targetFile := fmt.Sprintf("/tmp/%v.txt", cur)
	fileContent := fmt.Sprintf(`#!/bin/bash\r\n\r\n touch /tmp/%v.txt`, cur)
	action := &BashAction{Body: fileContent}

	eventsArray := make([]*events.Event, 1)
	eventsArray[0] = &events.Event{
		events.FirstEvent: time.Now(),
		events.LastEvent:  time.Now(),
		events.EventCount: 5,
		"event_severity":  5,
		"app_name":        "ASS",
	}

	err := action.Perform(&eventsArray)
	if err != nil {
		t.Errorf("Can't perform action: %v", err)
	}

	_, err = os.Stat(targetFile)
	if err != nil {
		t.Errorf("Can't get target file stat: %v", err)
	}
}
