// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 logtree

import (
	"errors"
	"strings"
	"sync"
)

// DN is the Distinguished Name, a dot-delimited path used to address loggers
// within a LogTree. For example, "foo.bar" designates the 'bar' logger node
// under the 'foo' logger node under the root node of the logger. An empty
// string is the root node of the tree.
type DN string

var (
	ErrInvalidDN = errors.New("invalid DN")
)

// Path return the parts of a DN, ie. all the elements of the dot-delimited DN
// path.  For the root node, an empty list will be returned. An error will be
// returned if the DN is invalid (contains empty parts, eg. `foo..bar`, `.foo`
// or `foo.`.
func (d DN) Path() ([]string, error) {
	if d == "" {
		return nil, nil
	}
	parts := strings.Split(string(d), ".")
	for _, p := range parts {
		if p == "" {
			return nil, ErrInvalidDN
		}
	}
	return parts, nil
}

// journal is the main log recording structure of logtree. It manages linked lists
// containing the actual log entries, and implements scans across them. It does not
// understand the hierarchical nature of logtree, and instead sees all entries as
// part of a global linked list and a local linked list for a given DN.
//
// The global linked list is represented by the head/tail pointers in journal and
// nextGlobal/prevGlobal pointers in entries. The local linked lists are
// represented by heads[DN]/tails[DN] pointers in journal and nextLocal/prevLocal
// pointers in entries:
//
//       .------------.        .------------.        .------------.
//       | dn: A.B    |        | dn: Z      |        | dn: A.B    |
//       | time: 1    |        | time: 2    |        | time: 3    |
//       |------------|        |------------|        |------------|
//       | nextGlobal :------->| nextGlobal :------->| nextGlobal :--> nil
// nil <-: prevGlobal |<-------: prevGlobal |<-------| prevGlobal |
//       |------------|        |------------|  n     |------------|
//       | nextLocal  :---. n  | nextLocal  :->i .-->| nextLocal  :--> nil
// nil <-: prevLocal  |<--: i<-: prevLocal  |  l :---| prevLocal  |
//       '------------'   | l  '------------'    |   '------------'
//            ^           '----------------------'         ^
//            |                      ^                     |
//            |                      |                     |
//         ( head )             ( tails[Z] )            ( tail )
//      ( heads[A.B] )          ( heads[Z] )         ( tails[A.B] )
type journal struct {
	// mu locks the rest of the structure. It must be taken during any operation on the
	// journal.
	mu sync.RWMutex

	// tail is the side of the global linked list that contains the newest log entry,
	// ie. the one that has been pushed the most recently. It can be nil when no log
	// entry has yet been pushed. The global linked list contains all log entries
	// pushed to the journal.
	tail *entry
	// head is the side of the global linked list that contains the oldest log entry.
	// It can be nil when no log entry has yet been pushed.
	head *entry

	// tails are the tail sides of a local linked list for a given DN, ie. the sides
	// that contain the newest entry. They are nil if there are no log entries for that
	// DN.
	tails map[DN]*entry
	// heads are the head sides of a local linked list for a given DN, ie. the sides
	// that contain the oldest entry. They are nil if there are no log entries for that
	// DN.
	heads map[DN]*entry

	// quota is a map from DN to quota structure, representing the quota policy of a
	// particular DN-designated logger.
	quota map[DN]*quota

	// subscribers are observer to logs. New log entries get emitted to channels
	// present in the subscriber structure, after filtering them through subscriber-
	// provided filters (eg. to limit events to subtrees that interest that particular
	// subscriber).
	subscribers []*subscriber
}

// newJournal creates a new empty journal. All journals are independent from
// eachother, and as such, all LogTrees are also independent.
func newJournal() *journal {
	return &journal{
		tails: make(map[DN]*entry),
		heads: make(map[DN]*entry),

		quota: make(map[DN]*quota),
	}
}

// filter is a predicate that returns true if a log subscriber or reader is
// interested in a given log entry.
type filter func(*entry) bool

// filterAll returns a filter that accepts all log entries.
func filterAll() filter {
	return func(*entry) bool { return true }
}

// filterExact returns a filter that accepts only log entries at a given exact
// DN.  This filter should not be used in conjunction with journal.scanEntries
// - instead, journal.getEntries should be used, as it is much faster.
func filterExact(dn DN) filter {
	return func(e *entry) bool {
		return e.origin == dn
	}
}

// filterSubtree returns a filter that accepts all log entries at a given DN and
// sub-DNs. For example, filterSubtree at "foo.bar" would allow entries at
// "foo.bar", "foo.bar.baz", but not "foo" or "foo.barr".
func filterSubtree(root DN) filter {
	if root == "" {
		return filterAll()
	}

	rootParts := strings.Split(string(root), ".")
	return func(e *entry) bool {
		parts := strings.Split(string(e.origin), ".")
		if len(parts) < len(rootParts) {
			return false
		}

		for i, p := range rootParts {
			if parts[i] != p {
				return false
			}
		}

		return true
	}
}

// filterSeverity returns a filter that accepts log entries at a given severity
// level or above. See the Severity type for more information about severity
// levels.
func filterSeverity(atLeast Severity) filter {
	return func(e *entry) bool {
		return e.leveled != nil && e.leveled.severity.AtLeast(atLeast)
	}
}

func filterOnlyRaw(e *entry) bool {
	return e.raw != nil
}

func filterOnlyLeveled(e *entry) bool {
	return e.leveled != nil
}

// scanEntries does a linear scan through the global entry list and returns all
// entries that match the given filters. If retrieving entries for an exact event,
// getEntries should be used instead, as it will leverage DN-local linked lists to
// retrieve them faster. journal.mu must be taken at R or RW level when calling
// this function.
func (j *journal) scanEntries(filters ...filter) (res []*entry) {
	cur := j.tail
	for {
		if cur == nil {
			return
		}

		passed := true
		for _, filter := range filters {
			if !filter(cur) {
				passed = false
				break
			}
		}
		if passed {
			res = append(res, cur)
		}
		cur = cur.nextGlobal
	}
}

// getEntries returns all entries at a given DN. This is faster than a
// scanEntries(filterExact), as it uses the special local linked list pointers to
// traverse the journal. Additional filters can be passed to further limit the
// entries returned, but a scan through this DN's local linked list will be
// performed regardless. journal.mu must be taken at R or RW level when calling
// this function.
func (j *journal) getEntries(exact DN, filters ...filter) (res []*entry) {
	cur := j.tails[exact]
	for {
		if cur == nil {
			return
		}

		passed := true
		for _, filter := range filters {
			if !filter(cur) {
				passed = false
				break
			}
		}
		if passed {
			res = append(res, cur)
		}
		cur = cur.nextLocal
	}

}
