<commit_before>package firego

import (
	"fmt"
	"sort"
	"strings"

	"github.com/zabawaba99/firego/sync"
)

// ChildEventFunc is the type of function that is called for every
// new child added under a firebase reference. The snapshot argument
// contains the data that was added. The previousChildKey argument
// contains the key of the previous child that this function was called for.
type ChildEventFunc func(snapshot DataSnapshot, previousChildKey string)

// ChildAdded listens on the firebase instance and executes the callback
// for every child that is added.
func (fb *Firebase) ChildAdded(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childAdded)
}

func (fn ChildEventFunc) childAdded(notifications chan Event) {
	var prevKey string
	db := sync.NewDB()

	for event := range notifications {
		if event.Type != EventTypePut {
			continue
		}

		child := strings.Split(event.Path[1:], "/")[0]
		if event.Data == nil {
			db.Del(child)
			continue
		}

		if _, ok := db.Get("").Child(child); ok {
			// if the child isn't being added, forget it
			continue
		}

		m, ok := event.Data.(map[string]interface{})
		if child == "" && ok {
			// if we were given a map at the root then we have
			// to send an event per child
			for _, k := range sortedKeys(m) {
				v := m[k]
				node := sync.NewNode(k, v)
				db.Add(k, node)
				fn(newSnapshot(node), prevKey)
				prevKey = k
			}
			continue
		}

		// we have a single event to process
		node := sync.NewNode(child, event.Data)
		db.Add(strings.Trim(child, "/"), node)

		fn(newSnapshot(node), prevKey)
		prevKey = child
	}
}

// ChildChanged listens on the firebase instance and executes the callback
// for every child that is changed.
func (fb *Firebase) ChildChanged(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childChanged)
}

func (fn ChildEventFunc) childChanged(notifications chan Event) {
	first, ok := <-notifications
	if !ok {
		return
	}

	db := sync.NewDB()
	db.Add("", sync.NewNode("", first.Data))

	var prevKey string
	for event := range notifications {
		path := strings.Trim(event.Path, "/")
		if event.Data == nil {
			db.Del(path)
			continue
		}

		child := strings.Split(path, "/")[0]
		node := sync.NewNode(child, event.Data)

		dbNode := db.Get("")
		if _, ok := dbNode.Child(child); child != "" && !ok {
			// if the child is new, ignore it.
			db.Add(path, node)
			continue
		}

		if m, ok := event.Data.(map[string]interface{}); child == "" && ok {
			// we've got children so send an event per child
			for _, k := range sortedKeys(m) {
				v := m[k]
				node := sync.NewNode(k, v)
				newPath := strings.TrimPrefix(child+"/"+k, "/")
				if _, ok := dbNode.Child(k); !ok {
					db.Add(newPath, node)
					continue
				}

				db.Update(newPath, node)
				fn(newSnapshot(node), prevKey)
				prevKey = k
			}
			continue
		}

		db.Update(path, node)
		fn(newSnapshot(db.Get(child)), prevKey)
		prevKey = child
	}
}

// ChildRemoved listens on the firebase instance and executes the callback
// for every child that is deleted.
func (fb *Firebase) ChildRemoved(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childRemoved)
}

func (fn ChildEventFunc) childRemoved(notifications chan Event) {
	first, ok := <-notifications
	if !ok {
		return
	}

	db := sync.NewDB()
	node := sync.NewNode("", first.Data)
	db.Add("", node)

	for event := range notifications {
		path := strings.Trim(event.Path, "/")
		node := sync.NewNode(path, event.Data)

		if event.Type == EventTypePatch {
			db.Update(path, node)
			continue
		}<commit_msg>Adding in the function overriding warning<commit_after>package firego

import (
	"fmt"
	"sort"
	"strings"

	"github.com/zabawaba99/firego/sync"
)

// ChildEventFunc is the type of function that is called for every
// new child added under a firebase reference. The snapshot argument
// contains the data that was added. The previousChildKey argument
// contains the key of the previous child that this function was called for.
type ChildEventFunc func(snapshot DataSnapshot, previousChildKey string)

// ChildAdded listens on the firebase instance and executes the callback
// for every child that is added.
//
// You cannot set the same function twice on a Firebase reference, if you do
// the first function will be overridden and you will not be able to close the
// connection.
func (fb *Firebase) ChildAdded(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childAdded)
}

func (fn ChildEventFunc) childAdded(notifications chan Event) {
	var prevKey string
	db := sync.NewDB()

	for event := range notifications {
		if event.Type != EventTypePut {
			continue
		}

		child := strings.Split(event.Path[1:], "/")[0]
		if event.Data == nil {
			db.Del(child)
			continue
		}

		if _, ok := db.Get("").Child(child); ok {
			// if the child isn't being added, forget it
			continue
		}

		m, ok := event.Data.(map[string]interface{})
		if child == "" && ok {
			// if we were given a map at the root then we have
			// to send an event per child
			for _, k := range sortedKeys(m) {
				v := m[k]
				node := sync.NewNode(k, v)
				db.Add(k, node)
				fn(newSnapshot(node), prevKey)
				prevKey = k
			}
			continue
		}

		// we have a single event to process
		node := sync.NewNode(child, event.Data)
		db.Add(strings.Trim(child, "/"), node)

		fn(newSnapshot(node), prevKey)
		prevKey = child
	}
}

// ChildChanged listens on the firebase instance and executes the callback
// for every child that is changed.
//
// You cannot set the same function twice on a Firebase reference, if you do
// the first function will be overridden and you will not be able to close the
// connection.
func (fb *Firebase) ChildChanged(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childChanged)
}

func (fn ChildEventFunc) childChanged(notifications chan Event) {
	first, ok := <-notifications
	if !ok {
		return
	}

	db := sync.NewDB()
	db.Add("", sync.NewNode("", first.Data))

	var prevKey string
	for event := range notifications {
		path := strings.Trim(event.Path, "/")
		if event.Data == nil {
			db.Del(path)
			continue
		}

		child := strings.Split(path, "/")[0]
		node := sync.NewNode(child, event.Data)

		dbNode := db.Get("")
		if _, ok := dbNode.Child(child); child != "" && !ok {
			// if the child is new, ignore it.
			db.Add(path, node)
			continue
		}

		if m, ok := event.Data.(map[string]interface{}); child == "" && ok {
			// we've got children so send an event per child
			for _, k := range sortedKeys(m) {
				v := m[k]
				node := sync.NewNode(k, v)
				newPath := strings.TrimPrefix(child+"/"+k, "/")
				if _, ok := dbNode.Child(k); !ok {
					db.Add(newPath, node)
					continue
				}

				db.Update(newPath, node)
				fn(newSnapshot(node), prevKey)
				prevKey = k
			}
			continue
		}

		db.Update(path, node)
		fn(newSnapshot(db.Get(child)), prevKey)
		prevKey = child
	}
}

// ChildRemoved listens on the firebase instance and executes the callback
// for every child that is deleted.
//
// You cannot set the same function twice on a Firebase reference, if you do
// the first function will be overridden and you will not be able to close the
// connection.
func (fb *Firebase) ChildRemoved(fn ChildEventFunc) error {
	return fb.addEventFunc(fn, fn.childRemoved)
}

func (fn ChildEventFunc) childRemoved(notifications chan Event) {
	first, ok := <-notifications
	if !ok {
		return
	}

	db := sync.NewDB()
	node := sync.NewNode("", first.Data)
	db.Add("", node)

	for event := range notifications {
		path := strings.Trim(event.Path, "/")
		node := sync.NewNode(path, event.Data)

		if event.Type == EventTypePatch {
			db.Update(path, node)
			continue
		}
{'fraction_non_alphanumeric': 0.12827225130890052, 'fraction_numerical': 0.0013089005235602095, 'mean_word_length': 3.2758813654169, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3576971', 'n_tokens_mistral': 2800, 'n_tokens_neox': 2472, 'n_words': 820}