/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 main

import (
	"fmt"
	"io/ioutil"
	"net"
	"org/apache/htrace/common"
	"org/apache/htrace/conf"
	"os"
	"strings"
)

//
// MiniHTraceD is used in unit tests to set up a daemon with certain settings.
// It takes care of things like creating and cleaning up temporary directories.
//

// The default number of managed data directories to use.
const DEFAULT_NUM_DATA_DIRS = 2

// Builds a MiniHTraced object.
type MiniHTracedBuilder struct {
	// The name of the MiniHTraced to build.  This shows up in the test directory name and some
	// other places.
	Name string

	// The configuration values to use for the MiniHTraced.
	// If ths is nil, we use the default configuration for everything.
	Cnf map[string]string

	// The DataDirs to use.  Empty entries will turn into random names.
	DataDirs []string

	// If true, we will keep the data dirs around after MiniHTraced#Close
	KeepDataDirsOnClose bool

	// If non-null, the WrittenSpans semaphore to use when creating the DataStore.
	WrittenSpans *common.Semaphore

	// The test hooks to use for the HRPC server
	HrpcTestHooks *hrpcTestHooks
}

type MiniHTraced struct {
	Name                string
	Cnf                 *conf.Config
	DataDirs            []string
	Store               *dataStore
	Rsv                 *RestServer
	Hsv                 *HrpcServer
	Lg                  *common.Logger
	KeepDataDirsOnClose bool
}

func (bld *MiniHTracedBuilder) Build() (*MiniHTraced, error) {
	var err error
	var store *dataStore
	var rsv *RestServer
	var hsv *HrpcServer
	if bld.Name == "" {
		bld.Name = "HTraceTest"
	}
	if bld.Cnf == nil {
		bld.Cnf = make(map[string]string)
	}
	if bld.DataDirs == nil {
		bld.DataDirs = make([]string, 2)
	}
	for idx := range bld.DataDirs {
		if bld.DataDirs[idx] == "" {
			bld.DataDirs[idx], err = ioutil.TempDir(os.TempDir(),
				fmt.Sprintf("%s%d", bld.Name, idx+1))
			if err != nil {
				return nil, err
			}
		}
	}
	// Copy the default test configuration values.
	for k, v := range conf.TEST_VALUES() {
		_, hasVal := bld.Cnf[k]
		if !hasVal {
			bld.Cnf[k] = v
		}
	}
	bld.Cnf[conf.HTRACE_DATA_STORE_DIRECTORIES] =
		strings.Join(bld.DataDirs, conf.PATH_LIST_SEP)
	cnfBld := conf.Builder{Values: bld.Cnf, Defaults: conf.DEFAULTS}
	cnf, err := cnfBld.Build()
	if err != nil {
		return nil, err
	}
	lg := common.NewLogger("mini.htraced", cnf)
	defer func() {
		if err != nil {
			if store != nil {
				store.Close()
			}
			for idx := range bld.DataDirs {
				if !bld.KeepDataDirsOnClose {
					if bld.DataDirs[idx] != "" {
						os.RemoveAll(bld.DataDirs[idx])
					}
				}
			}
			if rsv != nil {
				rsv.Close()
			}
			lg.Infof("Failed to create MiniHTraced %s: %s\n", bld.Name, err.Error())
			lg.Close()
		}
	}()
	store, err = CreateDataStore(cnf, bld.WrittenSpans)
	if err != nil {
		return nil, err
	}
	rstListener, listenErr := net.Listen("tcp", cnf.Get(conf.HTRACE_WEB_ADDRESS))
	if listenErr != nil {
		return nil, listenErr
	}
	defer func() {
		if rstListener != nil {
			rstListener.Close()
		}
	}()
	rsv, err = CreateRestServer(cnf, store, rstListener)
	if err != nil {
		return nil, err
	}
	rstListener = nil
	hsv, err = CreateHrpcServer(cnf, store, bld.HrpcTestHooks)
	if err != nil {
		return nil, err
	}

	lg.Infof("Created MiniHTraced %s\n", bld.Name)
	return &MiniHTraced{
		Name:                bld.Name,
		Cnf:                 cnf,
		DataDirs:            bld.DataDirs,
		Store:               store,
		Rsv:                 rsv,
		Hsv:                 hsv,
		Lg:                  lg,
		KeepDataDirsOnClose: bld.KeepDataDirsOnClose,
	}, nil
}

// Return a Config object that clients can use to connect to this MiniHTraceD.
func (ht *MiniHTraced) ClientConf() *conf.Config {
	return ht.Cnf.Clone(conf.HTRACE_WEB_ADDRESS, ht.Rsv.Addr().String(),
		conf.HTRACE_HRPC_ADDRESS, ht.Hsv.Addr().String())
}

// Return a Config object that clients can use to connect to this MiniHTraceD
// by HTTP only (no HRPC).
func (ht *MiniHTraced) RestOnlyClientConf() *conf.Config {
	return ht.Cnf.Clone(conf.HTRACE_WEB_ADDRESS, ht.Rsv.Addr().String(),
		conf.HTRACE_HRPC_ADDRESS, "")
}

func (ht *MiniHTraced) Close() {
	ht.Lg.Infof("Closing MiniHTraced %s\n", ht.Name)
	ht.Rsv.Close()
	ht.Hsv.Close()
	ht.Store.Close()
	if !ht.KeepDataDirsOnClose {
		for idx := range ht.DataDirs {
			ht.Lg.Infof("Removing %s...\n", ht.DataDirs[idx])
			os.RemoveAll(ht.DataDirs[idx])
		}
	}
	ht.Lg.Infof("Finished closing MiniHTraced %s\n", ht.Name)
	ht.Lg.Close()
}
