package urlstruct

import (
	"context"
	"net/url"
)

type Pager struct {
	Limit  int `urlstruct:"-"`
	Offset int `urlstruct:"-"`

	// Default max limit is 1000.
	MaxLimit int `urlstruct:"-"`
	// Default max offset is 1000000.
	MaxOffset int `urlstruct:"-"`

	stickyErr error
}

func NewPager(values url.Values) *Pager {
	p := new(Pager)
	p.stickyErr = p.UnmarshalValues(context.TODO(), values)
	return p
}

var _ Unmarshaler = (*Pager)(nil)

func (p *Pager) UnmarshalValues(ctx context.Context, values url.Values) error {
	vs := Values(values)

	limit, err := vs.Int("limit")
	if err != nil {
		return err
	}
	p.Limit = limit

	page, err := vs.Int("page")
	if err != nil {
		return err
	}
	p.SetPage(page)

	return nil
}

func (p *Pager) maxLimit() int {
	if p.MaxLimit > 0 {
		return p.MaxLimit
	}
	return 1000
}

func (p *Pager) maxOffset() int {
	if p.MaxOffset > 0 {
		return p.MaxOffset
	}
	return 1000000
}

func (p *Pager) GetLimit() int {
	const defaultLimit = 100

	if p == nil {
		return defaultLimit
	}
	if p.Limit < 0 {
		return p.Limit
	}
	if p.Limit == 0 {
		return defaultLimit
	}
	if p.Limit > p.maxLimit() {
		return p.maxLimit()
	}
	return p.Limit
}

func (p *Pager) GetOffset() int {
	if p == nil {
		return 0
	}
	if p.Offset > p.maxOffset() {
		return p.maxOffset()
	}
	return p.Offset
}

func (p *Pager) SetPage(page int) {
	if page < 1 {
		page = 1
	}
	p.Offset = (page - 1) * p.GetLimit()
}

func (p *Pager) GetPage() int {
	return (p.GetOffset() / p.GetLimit()) + 1
}