/*
 * Copyright (C) 2017-2018 "IoT.bzh"
 * Author Clément Bénier <clement.benier@iot.bzh>
 *
 * 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 xdsservertest

import (
	"io/ioutil"
	"os"
	"regexp"
	"testing"

	"gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
	"github.com/stretchr/testify/assert"
)

func TestFolders(t *testing.T) {
	var cfgArray []xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	assert.Equal(t, len(cfgArray), 0)

	fPrj := xsapiv1.FolderConfig{
		Label:      "testproject",
		ClientPath: logDir + "testproject",
		Type:       xsapiv1.TypePathMap,
		ClientData: "clientdatatest",
		DataPathMap: xsapiv1.PathMapConfig{
			ServerPath: logDir + "testserverpath",
		},
	}
	var cfg xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	assert.NotNil(t, cfg)

	isCfgPrjMatch := func(fPrj xsapiv1.FolderConfig, cfg xsapiv1.FolderConfig) {
		re := regexp.MustCompile("^[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+$")
		assert.True(t, re.MatchString(cfg.ID)) //ID
		assert.Equal(t, cfg.Label, fPrj.Label) //Label
		assert.Equal(t, cfg.ClientPath, fPrj.ClientPath)
		assert.Equal(t, cfg.Type, fPrj.Type)
		assert.Equal(t, cfg.Status, "Enable")
		assert.Equal(t, cfg.IsInSync, true)
		assert.Equal(t, len(cfg.DefaultSdk), 0)
		assert.Equal(t, fPrj.ClientData, cfg.ClientData)
		assert.Equal(t, fPrj.DataPathMap.ServerPath, cfg.DataPathMap.ServerPath)
	}
	isCfgPrjMatch(fPrj, cfg)
	var cfg2 xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Get("/folders/"+cfg.ID, &cfg2))
	isCfgPrjMatch(fPrj, cfg2)

	assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	assert.Equal(t, len(cfgArray), 1)

	//call with the same uid create error
	assert.NotNil(t, HTTPCli.Post("/folders", cfg, &cfg))

	/*create/delete folders*/
	var cfgArrayBis []xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	assert.Equal(t, len(cfgArray), 3)
	assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[1].ID, &cfg))
	assert.Equal(t, cfg, cfgArray[1])
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	assert.Equal(t, len(cfgArrayBis), 2)
	assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[0].ID, &cfg))
	assert.Equal(t, cfg, cfgArray[0])
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	assert.Equal(t, len(cfgArrayBis), 1)
	assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[2].ID, &cfg))
	assert.Equal(t, cfg, cfgArray[2])
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	assert.Equal(t, len(cfgArrayBis), 0)
}

func TestFoldersEmptyValues(t *testing.T) {
	fPrj := xsapiv1.FolderConfig{
		Label:      "testproject",
		ClientPath: logDir + "testproject",
		Type:       xsapiv1.TypePathMap,
		ClientData: "clientdatatest",
		DataPathMap: xsapiv1.PathMapConfig{
			ServerPath: "",
		},
	}
	var cfg xsapiv1.FolderConfig
	/*ServerPath is empty*/
	assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	fPrj.DataPathMap.ServerPath = logDir + "sameserverpath"
	fPrj.ClientPath = ""
	/*ClientPath is Empty*/
	assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	fPrj.ClientPath = "logDir"
	fPrj.Type = ""
	/*Type is empty*/
	assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	var cfgArray []xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	assert.Equal(t, len(cfgArray), 0)
}

func TestFoldersPathMapConfig(t *testing.T) {
	fPrj := xsapiv1.FolderConfig{
		Label:      "testproject",
		ClientPath: logDir + "clientpathtest",
		Type:       xsapiv1.TypePathMap,
		ClientData: "clientdatatest",
		DataPathMap: xsapiv1.PathMapConfig{
			ServerPath: logDir + "serverpath",
			CheckFile:  "checkfile",
		},
	}
	var cfg xsapiv1.FolderConfig
	/*file not present*/
	assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	var checkFileClient = fPrj.ClientPath + "/checkfile"
	var checkFileServer = fPrj.DataPathMap.ServerPath + "/checkfile"

	/*create file*/
	os.MkdirAll(fPrj.ClientPath, 0755)
	fPrj.DataPathMap.CheckFile = checkFileClient
	fPrj.DataPathMap.CheckContent = "CheckContent From Client\n"
	file, err := os.OpenFile(checkFileClient, os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		t.Log(err)
	}
	if err := os.Symlink(checkFileClient, checkFileServer); err != nil {
		t.Log(err)
	}
	/*file content differ*/
	assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	/*write same message*/
	if _, err := file.WriteString(fPrj.DataPathMap.CheckContent); err != nil {
		t.Log(err)
	}
	assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))

	/*check server msg: ServerUID needed*/
	var APIcfg xsapiv1.APIConfig
	assert.Nil(t, HTTPCli.Get("/config", &APIcfg))
	msg := "Pathmap checked message written by xds-server ID: " + APIcfg.ServerUID + "\n"
	data, err := ioutil.ReadAll(file)
	if err != nil {
		t.Log(err)
	}
	assert.Equal(t, msg, string(data))

	assert.Nil(t, HTTPCli.Delete("/folders/"+cfg.ID, &cfg))
	var cfgArray []xsapiv1.FolderConfig
	assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	assert.Equal(t, len(cfgArray), 0)
}