// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The iterable package provides several traversal and searching methods.
// It can be used on anything that satisfies the Iterable interface,
// including vector, though certain functions, such as Map, can also be used on
// something that would produce an infinite amount of data.
package iterable

import (
	"container/list"
	"container/vector"
)

type Iterable interface {
	// Iter should return a fresh channel each time it is called.
	Iter() <-chan interface{}
}

func not(f func(interface{}) bool) (func(interface{}) bool) {
	return func(e interface{}) bool { return !f(e) }
}

// All tests whether f is true for every element of iter.
func All(iter Iterable, f func(interface{}) bool) bool {
	for e := range iter.Iter() {
		if !f(e) {
			return false
		}
	}
	return true
}

// Any tests whether f is true for at least one element of iter.
func Any(iter Iterable, f func(interface{}) bool) bool {
	return !All(iter, not(f))
}

// Data returns a slice containing the elements of iter.
func Data(iter Iterable) []interface{} {
	vec := new(vector.Vector)
	for e := range iter.Iter() {
		vec.Push(e)
	}
	return vec.Data()
}

// filteredIterable is a struct that implements Iterable with each element
// passed through a filter.
type filteredIterable struct {
	it Iterable
	f  func(interface{}) bool
}

func (f *filteredIterable) iterate(out chan<- interface{}) {
	for e := range f.it.Iter() {
		if f.f(e) {
			out <- e
		}
	}
	close(out)
}

func (f *filteredIterable) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go f.iterate(ch)
	return ch
}

// Filter returns an Iterable that returns the elements of iter that satisfy f.
func Filter(iter Iterable, f func(interface{}) bool) Iterable {
	return &filteredIterable{iter, f}
}

// Find returns the first element of iter that satisfies f.
// Returns nil if no such element is found.
func Find(iter Iterable, f func(interface{}) bool) interface{} {
	for e := range Filter(iter, f).Iter() {
		return e
	}
	return nil
}

// Injector is a type representing a function that takes two arguments,
// an accumulated value and an element, and returns the next accumulated value.
// See the Inject function.
type Injector func(interface{}, interface{}) interface{}

// Inject combines the elements of iter by repeatedly calling f with an
// accumulated value and each element in order. The starting accumulated value
// is initial, and after each call the accumulated value is set to the return
// value of f. For instance, to compute a sum:
//   var arr IntArray = []int{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//   sum := iterable.Inject(arr, 0,
//                          func(ax interface {}, x interface {}) interface {} {
//                            return ax.(int) + x.(int) }).(int)
func Inject(iter Iterable, initial interface{}, f Injector) interface{} {
	acc := initial
	for e := range iter.Iter() {
		acc = f(acc, e)
	}
	return acc
}

// mappedIterable is a helper struct that implements Iterable, returned by Map.
type mappedIterable struct {
	it Iterable
	f  func(interface{}) interface{}
}

func (m *mappedIterable) iterate(out chan<- interface{}) {
	for e := range m.it.Iter() {
		out <- m.f(e)
	}
	close(out)
}

func (m *mappedIterable) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go m.iterate(ch)
	return ch
}

// Map returns an Iterable that returns the result of applying f to each
// element of iter.
func Map(iter Iterable, f func(interface{}) interface{}) Iterable {
	return &mappedIterable{iter, f}
}

// Partition(iter, f) returns Filter(iter, f) and Filter(iter, !f).
func Partition(iter Iterable, f func(interface{}) bool) (Iterable, Iterable) {
	return Filter(iter, f), Filter(iter, not(f))
}

// helper type for the Take/TakeWhile/Drop/DropWhile functions.
// primarily used so that the .Iter() method can be attached
type iterFunc func(chan<- interface{})

// provide the Iterable interface
func (v iterFunc) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go v(ch)
	return ch
}

// Take returns an Iterable that contains the first n elements of iter.
func Take(iter Iterable, n int) Iterable { return Slice(iter, 0, n) }

// TakeWhile returns an Iterable that contains elements from iter while f is true.
func TakeWhile(iter Iterable, f func(interface{}) bool) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		for v := range iter.Iter() {
			if !f(v) {
				break
			}
			ch <- v
		}
		close(ch)
	})
}

// Drop returns an Iterable that returns each element of iter after the first n elements.
func Drop(iter Iterable, n int) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		m := n
		for v := range iter.Iter() {
			if m > 0 {
				m--
				continue
			}
			ch <- v
		}
		close(ch)
	})
}

// DropWhile returns an Iterable that returns each element of iter after the initial sequence for which f returns true.
func DropWhile(iter Iterable, f func(interface{}) bool) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		drop := true
		for v := range iter.Iter() {
			if drop {
				if f(v) {
					continue
				}
				drop = false
			}
			ch <- v
		}
		close(ch)
	})
}

// Cycle repeats the values of iter in order infinitely.
func Cycle(iter Iterable) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		for {
			for v := range iter.Iter() {
				ch <- v
			}
		}
	})
}

// Chain returns an Iterable that concatentates all values from the specified Iterables.
func Chain(args []Iterable) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		for _, e := range args {
			for v := range e.Iter() {
				ch <- v
			}
		}
		close(ch)
	})
}

// Zip returns an Iterable of []interface{} consisting of the next element from
// each input Iterable.  The length of the returned Iterable is the minimum of
// the lengths of the input Iterables.
func Zip(args []Iterable) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		defer close(ch)
		if len(args) == 0 {
			return
		}
		iters := make([]<-chan interface{}, len(args))
		for i := 0; i < len(iters); i++ {
			iters[i] = args[i].Iter()
		}
		for {
			out := make([]interface{}, len(args))
			for i, v := range iters {
				out[i] = <-v
				if closed(v) {
					return
				}
			}
			ch <- out
		}
	})
}

// ZipWith returns an Iterable containing the result of executing f using arguments read from a and b.
func ZipWith2(f func(c, d interface{}) interface{}, a, b Iterable) Iterable {
	return Map(Zip([]Iterable{a, b}), func(a1 interface{}) interface{} {
		arr := a1.([]interface{})
		return f(arr[0], arr[1])
	})
}

// ZipWith returns an Iterable containing the result of executing f using arguments read from a, b and c.
func ZipWith3(f func(d, e, f interface{}) interface{}, a, b, c Iterable) Iterable {
	return Map(Zip([]Iterable{a, b, c}), func(a1 interface{}) interface{} {
		arr := a1.([]interface{})
		return f(arr[0], arr[1], arr[2])
	})
}

// Slice returns an Iterable that contains the elements from iter
// with indexes in [start, stop).
func Slice(iter Iterable, start, stop int) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		defer close(ch)
		i := 0
		for v := range iter.Iter() {
			switch {
			case i >= stop:
				return
			case i >= start:
				ch <- v
			}
			i++
		}
	})
}

// Repeat generates an infinite stream of v.
func Repeat(v interface{}) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		for {
			ch <- v
		}
	})
}

// RepeatTimes generates a stream of n copies of v.
func RepeatTimes(v interface{}, n int) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		for i := 0; i < n; i++ {
			ch <- v
		}
		close(ch)
	})
}

// Group is the type for elements returned by the GroupBy function.
type Group struct {
	Key  interface{} // key value for matching items
	Vals Iterable    // Iterable for receiving values in the group
}

// Key defines the interface required by the GroupBy function.
type Grouper interface {
	// Return the key for the given value
	Key(interface{}) interface{}

	// Compute equality for the given keys
	Equal(a, b interface{}) bool
}

// GroupBy combines sequences of logically identical values from iter using k
// to generate a key to compare values.  Each value emitted by the returned
// Iterable is of type Group, which contains the key used for matching the
// values for the group, and an Iterable for retrieving all the values in the
// group.
func GroupBy(iter Iterable, k Grouper) Iterable {
	return iterFunc(func(ch chan<- interface{}) {
		var curkey interface{}
		var lst *list.List
		// Basic strategy is to read one group at a time into a list prior to emitting the Group value
		for v := range iter.Iter() {
			kv := k.Key(v)
			if lst == nil || !k.Equal(curkey, kv) {
				if lst != nil {
					ch <- Group{curkey, lst}
				}
				lst = list.New()
				curkey = kv
			}
			lst.PushBack(v)
		}
		if lst != nil {
			ch <- Group{curkey, lst}
		}
		close(ch)
	})
}

// Unique removes duplicate values which occur consecutively using id to compute keys.
func Unique(iter Iterable, id Grouper) Iterable {
	return Map(GroupBy(iter, id), func(v interface{}) interface{} { return v.(Group).Key })
}
