/*
 * 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 common

import (
	"bufio"
	"fmt"
	"htrace/conf"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func newLogger(faculty string, args ...string) *Logger {
	cnfBld := conf.Builder{Defaults: conf.DEFAULTS}
	cnf, err := cnfBld.Build()
	if err != nil {
		panic(fmt.Sprintf("failed to create conf: %s", err.Error()))
	}
	cnf2 := cnf.Clone(args...)
	lg := NewLogger(faculty, cnf2)
	return lg
}

func TestNewLogger(t *testing.T) {
	lg := newLogger("foo", "log.level", "TRACE")
	lg.Close()
}

func verifyLines(t *testing.T, rdr io.Reader, lines []string) {
	scanner := bufio.NewScanner(rdr)
	lineIdx := 0
	for scanner.Scan() {
		line := scanner.Text()
		if !strings.Contains(line, lines[lineIdx]) {
			t.Fatalf("Error on line %d: didn't find substring '%s' in line '%s'\n",
				(lineIdx + 1), lines[lineIdx], line)
		}
		lineIdx++
	}
	if err := scanner.Err(); err != nil {
		t.Fatal(err.Error())
	}
}

func TestFileLogs(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "testFileLogs")
	if err != nil {
		panic(fmt.Sprintf("error creating tempdir: %s\n", err.Error()))
	}
	defer os.RemoveAll(tempDir)
	logPath := tempDir + conf.PATH_SEP + "log"
	lg := newLogger("foo", "log.level", "DEBUG",
		"foo.log.level", "INFO",
		"log.path", logPath)
	lg.Tracef("Non-important stuff, ignore this.\n")
	lg.Infof("problem with the foobar\n")
	lg.Tracef("More non-important stuff, also ignore this.\n")
	lg.Infof("and another problem with the foobar\n")
	logFile, err := os.Open(logPath)
	if err != nil {
		t.Fatalf("failed to open file %s: %s\n", logPath, err.Error())
	}
	verifyLines(t, logFile, []string{
		"problem with the foobar",
		"and another problem with the foobar",
	})
	logFile.Close()
	lg.Close()
}

func TestMultipleFileLogs(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "testMultipleFileLogs")
	if err != nil {
		panic(fmt.Sprintf("error creating tempdir: %s\n", err.Error()))
	}
	defer os.RemoveAll(tempDir)
	logPath := tempDir + conf.PATH_SEP + "log"
	fooLg := newLogger("foo", "log.level", "DEBUG",
		"foo.log.level", "INFO",
		"log.path", logPath)
	fooLg.Infof("The foo needs maintenance.\n")
	barLg := newLogger("bar", "log.level", "DEBUG",
		"foo.log.level", "INFO",
		"log.path", logPath)
	barLg.Debugf("The bar is open\n")
	fooLg.Errorf("Fizz buzz\n")
	logFile, err := os.Open(logPath)
	if err != nil {
		t.Fatalf("failed to open file %s: %s\n", logPath, err.Error())
	}
	fooLg.Tracef("Fizz buzz2\n")
	barLg.Tracef("Fizz buzz3\n")
	verifyLines(t, logFile, []string{
		"The foo needs maintenance.",
		"The bar is open",
		"Fizz buzz",
		"Fizz buzz3",
	})
	logFile.Close()
	fooLg.Close()
	barLg.Close()
}

func TestLogLevelEnabled(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "TestLogLevelEnabled")
	if err != nil {
		panic(fmt.Sprintf("error creating tempdir: %s\n", err.Error()))
	}
	defer os.RemoveAll(tempDir)
	// set log level to DEBUG for facility "foo"
	logPath := tempDir + conf.PATH_SEP + "log"
	lg := newLogger("foo", "log.level", "DEBUG",
		"foo.log.level", "INFO",
		"log.path", logPath)
	if lg.TraceEnabled() {
		t.Fatalf("foo logger has TraceEnabled")
	}
	if lg.DebugEnabled() {
		t.Fatalf("foo logger have DebugEnabled")
	}
	if !lg.InfoEnabled() {
		t.Fatalf("foo logger does not have InfoEnabled")
	}
	if !lg.WarnEnabled() {
		t.Fatalf("foo logger does not have WarnEnabled")
	}
	if !lg.ErrorEnabled() {
		t.Fatalf("foo logger does not have ErrorEnabled")
	}
	lg.Close()
	lg = newLogger("foo", "log.level", "WARN",
		"foo.log.level", "INFO",
		"log.path", logPath)
	if lg.TraceEnabled() {
		t.Fatalf("foo logger has TraceEnabled")
	}
	if lg.DebugEnabled() {
		t.Fatalf("foo logger has DebugEnabled")
	}
	if !lg.InfoEnabled() {
		t.Fatalf("foo logger does not have InfoEnabled")
	}
	if !lg.WarnEnabled() {
		t.Fatalf("foo logger does not have WarnEnabled")
	}
	if !lg.ErrorEnabled() {
		t.Fatalf("foo logger does not have ErrorEnabled")
	}
	lg.Close()
}
