/*
 * 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.git/lib/xsapiv1"
	"github.com/stretchr/testify/require"
)

func TestFolders(t *testing.T) {
	/*init: check there is no folder*/
	Debug(t, "check there is no folder")
	var cfgArray []xsapiv1.FolderConfig
	require.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	require.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
	Debugf(t, "create folder: \n%v", fPrj)
	require.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	require.NotNil(t, cfg)
	Debugf(t, "result folder: \n%v", 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]+$")
		require.True(t, re.MatchString(cfg.ID)) //ID
		require.Equal(t, cfg.Label, fPrj.Label) //Label
		require.Equal(t, cfg.ClientPath, fPrj.ClientPath)
		require.Equal(t, cfg.Type, fPrj.Type)
		require.Equal(t, cfg.Status, "Enable")
		require.Equal(t, cfg.IsInSync, true)
		require.Equal(t, len(cfg.DefaultSdk), 0)
		require.Equal(t, fPrj.ClientData, cfg.ClientData)
		require.Equal(t, fPrj.DataPathMap.ServerPath, cfg.DataPathMap.ServerPath)
	}
	isCfgPrjMatch(fPrj, cfg)
	var cfg2 xsapiv1.FolderConfig
	require.Nil(t, HTTPCli.Get("/folders/"+cfg.ID, &cfg2))
	isCfgPrjMatch(fPrj, cfg2)

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

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

	/*create/delete folders*/
	var cfgArrayBis []xsapiv1.FolderConfig
	require.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "create folder with id=%v", cfg.ID)
	require.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "create folder with id=%v", cfg.ID)
	require.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	require.Equal(t, len(cfgArray), 3)
	require.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[1].ID, &cfg))
	Debugf(t, "delete folder with id=%v", cfg.ID)
	require.Equal(t, cfg, cfgArray[1])
	require.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	require.Equal(t, len(cfgArrayBis), 2)
	require.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[0].ID, &cfg))
	Debugf(t, "delete folder with id=%v", cfg.ID)
	require.Equal(t, cfg, cfgArray[0])
	require.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	require.Equal(t, len(cfgArrayBis), 1)
	require.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[2].ID, &cfg))
	Debugf(t, "delete folder with id=%v", cfg.ID)
	require.Equal(t, cfg, cfgArray[2])
	require.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
	require.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*/
	require.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "error while creating folder with empty serverpath \n%v", fPrj)

	fPrj.DataPathMap.ServerPath = logDir + "sameserverpath"
	fPrj.ClientPath = ""
	/*ClientPath is Empty*/
	require.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "error while creating folder with empty clientpath \n%v", fPrj)

	fPrj.ClientPath = "logDir"
	fPrj.Type = ""
	/*Type is empty*/
	require.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "error while creating folder with empty type \n%v", fPrj)

	var cfgArray []xsapiv1.FolderConfig
	require.Nil(t, HTTPCli.Get("/folders", &cfgArray))
	require.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*/
	require.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "error while creating folder with no checkfile \n%v", fPrj)

	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 {
		Debug(t, err)
	}
	if err := os.Symlink(checkFileClient, checkFileServer); err != nil {
		Debug(t, err)
	}
	/*file content differ*/
	require.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "error while creating folder with different checkfiles \n%v", fPrj)

	/*write same message*/
	if _, err := file.WriteString(fPrj.DataPathMap.CheckContent); err != nil {
		Debug(t, err)
	}
	require.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
	Debugf(t, "create folder with same checkfiles \n%v", fPrj)

	/*check server msg: ServerUID needed*/
	Debugf(t, "check server msg")
	var APIcfg xsapiv1.APIConfig
	require.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 {
		Debug(t, err)
	}
	require.Equal(t, msg, string(data))

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