package data

import (
	"encoding/gob"
	"fmt"
	"os"
	"sync"

	"github.com/gorilla/feeds"
)

type Feed struct {
	addCh chan *feeds.Item
	setCh chan feeds.Feed
	getCh chan feeds.Feed
	feed  feeds.Feed
	wg    sync.WaitGroup
}

func minFeed() *Feed {
	return &Feed{
		addCh: make(chan *feeds.Item),
		setCh: make(chan feeds.Feed),
		getCh: make(chan feeds.Feed),
	}
}

func (f *Feed) start() {
	f.wg.Done()
	for {
		select {
		case item := <-f.addCh:
			f.feed.Items = append(f.feed.Items, item)
		case f.getCh <- f.feed:
		case f.feed = <-f.setCh:
		}
	}
}

func NewFeed(title, link, desc string) *Feed {
	feed := minFeed()
	feed.feed = feeds.Feed{
		Title:       title,
		Link:        &feeds.Link{Href: link},
		Description: desc,
	}

	feed.wg.Add(1)
	go feed.start()
	feed.wg.Wait()

	return feed
}

func (f *Feed) Get() feeds.Feed {
	return <-f.getCh
}

func (f *Feed) Set(feed feeds.Feed) {
	f.setCh <- feed
}

func OpenFeed(filename string) (*Feed, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("error opening file %v: %v", filename, err)
	}
	defer file.Close()

	feed := minFeed()
	feed.wg.Add(1)
	go feed.start()
	feed.wg.Wait()

	decoder := gob.NewDecoder(file)
	tmpFeed := new(feeds.Feed)
	err = decoder.Decode(tmpFeed)
	if err != nil {
		return nil, fmt.Errorf("error decoding file %v: %v", filename, err)
	}

	feed.Set(*tmpFeed)

	return feed, nil
}

func (f *Feed) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("error creating file %v: %v", filename, err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)
	feed := f.Get()
	err = encoder.Encode(feed)
	if err != nil {
		return fmt.Errorf("error encoding file %v: %v", filename, err)
	}

	return nil
}

func (f *Feed) Add(i *feeds.Item) {
	f.addCh <- i
}