/*
 * 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"
	"io"
	"io/ioutil"
	"org/apache/htrace/conf"
	"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()
}
