package pagination

import (
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"github.com/gophercloud/gophercloud"
)

var (
	// ErrPageNotAvailable is returned from a Pager when a next or previous page is requested, but does not exist.
	ErrPageNotAvailable = errors.New("The requested page does not exist.")
)

// Page must be satisfied by the result type of any resource collection.
// It allows clients to interact with the resource uniformly, regardless of whether or not or how it's paginated.
// Generally, rather than implementing this interface directly, implementors should embed one of the concrete PageBase structs,
// instead.
// Depending on the pagination strategy of a particular resource, there may be an additional subinterface that the result type
// will need to implement.
type Page interface {
	// NextPageURL generates the URL for the page of data that follows this collection.
	// Return "" if no such page exists.
	NextPageURL() (string, error)

	// IsEmpty returns true if this Page has no items in it.
	IsEmpty() (bool, error)

	// GetBody returns the Page Body. This is used in the `AllPages` method.
	GetBody() interface{}
}

// Pager knows how to advance through a specific resource collection, one page at a time.
type Pager struct {
	client *gophercloud.ServiceClient

	initialURL string

	createPage func(r PageResult) Page

	firstPage Page

	Err error

	// Headers supplies additional HTTP headers to populate on each paged request.
	Headers map[string]string
}

// NewPager constructs a manually-configured pager.
// Supply the URL for the first page, a function that requests a specific page given a URL, and a function that counts a page.
func NewPager(client *gophercloud.ServiceClient, initialURL string, createPage func(r PageResult) Page) Pager {
	return Pager{
		client:     client,
		initialURL: initialURL,
		createPage: createPage,
	}
}

// WithPageCreator returns a new Pager that substitutes a different page creation function. This is
// useful for overriding List functions in delegation.
func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager {
	return Pager{
		client:     p.client,
		initialURL: p.initialURL,
		createPage: createPage,
	}
}

func (p Pager) fetchNextPage(url string) (Page, error) {
	resp, err := Request(p.client, p.Headers, url)
	if err != nil {
		return nil, err
	}

	remembered, err := PageResultFrom(resp)
	if err != nil {
		return nil, err
	}

	return p.createPage(remembered), nil
}

// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function.
// Return "false" from the handler to prematurely stop iterating.
func (p Pager) EachPage(handler func(Page) (bool, error)) error {
	if p.Err != nil {
		return p.Err
	}
	currentURL := p.initialURL
	for {
		var currentPage Page

		// if first page has already been fetched, no need to fetch it again
		if p.firstPage != nil {
			currentPage = p.firstPage
			p.firstPage = nil
		} else {
			var err error
			currentPage, err = p.fetchNextPage(currentURL)
			if err != nil {
				return err
			}
		}

		empty, err := currentPage.IsEmpty()
		if err != nil {
			return err
		}
		if empty {
			return nil
		}

		ok, err := handler(currentPage)
		if err != nil {
			return err
		}
		if !ok {
			return nil
		}

		currentURL, err = currentPage.NextPageURL()
		if err != nil {
			return err
		}
		if currentURL == "" {
			return nil
		}
	}
}

// AllPages returns all the pages from a `List` operation in a single page,
// allowing the user to retrieve all the pages at once.
func (p Pager) AllPages() (Page, error) {
	// pagesSlice holds all the pages until they get converted into as Page Body.
	var pagesSlice []interface{}
	// body will contain the final concatenated Page body.
	var body reflect.Value

	// Grab a first page to ascertain the page body type.
	firstPage, err := p.fetchNextPage(p.initialURL)
	if err != nil {
		return nil, err
	}
	// Store the page type so we can use reflection to create a new mega-page of
	// that type.
	pageType := reflect.TypeOf(firstPage)

	// if it's a single page, just return the firstPage (first page)
	if _, found := pageType.FieldByName("SinglePageBase"); found {
		return firstPage, nil
	}

	// store the first page to avoid getting it twice
	p.firstPage = firstPage

	// Switch on the page body type. Recognized types are `map[string]interface{}`,
	// `[]byte`, and `[]interface{}`.
	switch pb := firstPage.GetBody().(type) {
	case map[string]interface{}:
		// key is the map key for the page body if the body type is `map[string]interface{}`.
		var key string
		// Iterate over the pages to concatenate the bodies.
		err = p.EachPage(func(page Page) (bool, error) {
			b := page.GetBody().(map[string]interface{})
			for k, v := range b {
				// If it's a linked page, we don't want the `links`, we want the other one.
				if !strings.HasSuffix(k, "links") {
					// check the field's type. we only want []interface{} (which is really []map[string]interface{})
					switch vt := v.(type) {
					case []interface{}:
						key = k
						pagesSlice = append(pagesSlice, vt...)
					}
				}
			}
			return true, nil
		})
		if err != nil {
			return nil, err
		}
		// Set body to value of type `map[string]interface{}`
		body = reflect.MakeMap(reflect.MapOf(reflect.TypeOf(key), reflect.TypeOf(pagesSlice)))
		body.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(pagesSlice))
	case []byte:
		// Iterate over the pages to concatenate the bodies.
		err = p.EachPage(func(page Page) (bool, error) {
			b := page.GetBody().([]byte)
			pagesSlice = append(pagesSlice, b)
			// seperate pages with a comma
			pagesSlice = append(pagesSlice, []byte{10})
			return true, nil
		})
		if err != nil {
			return nil, err
		}
		if len(pagesSlice) > 0 {
			// Remove the trailing comma.
			pagesSlice = pagesSlice[:len(pagesSlice)-1]
		}
		var b []byte
		// Combine the slice of slices in to a single slice.
		for _, slice := range pagesSlice {
			b = append(b, slice.([]byte)...)
		}
		// Set body to value of type `bytes`.
		body = reflect.New(reflect.TypeOf(b)).Elem()
		body.SetBytes(b)
	case []interface{}:
		// Iterate over the pages to concatenate the bodies.
		err = p.EachPage(func(page Page) (bool, error) {
			b := page.GetBody().([]interface{})
			pagesSlice = append(pagesSlice, b...)
			return true, nil
		})
		if err != nil {
			return nil, err
		}
		// Set body to value of type `[]interface{}`
		body = reflect.MakeSlice(reflect.TypeOf(pagesSlice), len(pagesSlice), len(pagesSlice))
		for i, s := range pagesSlice {
			body.Index(i).Set(reflect.ValueOf(s))
		}
	default:
		err := gophercloud.ErrUnexpectedType{}
		err.Expected = "map[string]interface{}/[]byte/[]interface{}"
		err.Actual = fmt.Sprintf("%T", pb)
		return nil, err
	}

	// Each `Extract*` function is expecting a specific type of page coming back,
	// otherwise the type assertion in those functions will fail. pageType is needed
	// to create a type in this method that has the same type that the `Extract*`
	// function is expecting and set the Body of that object to the concatenated
	// pages.
	page := reflect.New(pageType)
	// Set the page body to be the concatenated pages.
	page.Elem().FieldByName("Body").Set(body)
	// Set any additional headers that were pass along. The `objectstorage` pacakge,
	// for example, passes a Content-Type header.
	h := make(http.Header)
	for k, v := range p.Headers {
		h.Add(k, v)
	}
	page.Elem().FieldByName("Header").Set(reflect.ValueOf(h))
	// Type assert the page to a Page interface so that the type assertion in the
	// `Extract*` methods will work.
	return page.Elem().Interface().(Page), err
}
