package liber

import (
	"encoding/xml"
	"io"
	"os"
	"path/filepath"
	"strings"
)

type opfIdentifier struct {
	Scheme string `xml:"http://www.idpf.org/2007/opf scheme,attr"`
	Value  string `xml:",chardata"`
}

type opfMeta struct {
	XMLName     xml.Name        `xml:"http://www.idpf.org/2007/opf metadata"`
	Title       string          `xml:"http://purl.org/dc/elements/1.1/ title"`
	Date        string          `xml:"http://purl.org/dc/elements/1.1/ date"`
	Description string          `xml:"http://purl.org/dc/elements/1.1/ description"`
	Creator     []string        `xml:"http://purl.org/dc/elements/1.1/ creator"`
	Language    []string        `xml:"http://purl.org/dc/elements/1.1/ language"`
	Publisher   []string        `xml:"http://purl.org/dc/elements/1.1/ publisher"`
	Identifier  []opfIdentifier `xml:"http://purl.org/dc/elements/1.1/ identifier"`
}

type opfPackage struct {
	Meta *opfMeta
}

func (o *opfMeta) ToMetadata() *Metadata {
	m := &Metadata{
		Title:       o.Title,
		Description: o.Description,
		Publisher:   o.Publisher,
		Language:    o.Language,
	}
	if o.Date != "" && o.Date != "0101-01-01T00:00:00+00:00" {
		m.Date = toYear(o.Date)
	}
	for _, c := range o.Creator {
		for _, cc := range strings.Split(c, ",") {
			m.Creator = append(m.Creator, strings.TrimSpace(cc))
		}
	}
	var uuid string
	for _, id := range o.Identifier {
		if id.Scheme == "ISBN" {
			m.ISBN = append(m.ISBN, id.Value)
		} else if id.Scheme == "uuid" {
			uuid = id.Value
		}
	}
	m.Sources = []MetadataSource{{
		Name: "opf",
		ID:   uuid,
	}}
	return m
}

func opfParse(r io.Reader) (*Metadata, error) {
	var opf opfPackage
	if err := xml.NewDecoder(r).Decode(&opf); err != nil {
		return nil, err
	}
	return opf.Meta.ToMetadata(), nil
}

func opfOpen(path string) (*Metadata, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return opfParse(file)
}

func opfMetadataPath(epubPath string) string {
	return filepath.Join(filepath.Dir(epubPath), "metadata.opf")
}

func opfCoverPath(epubPath string) string {
	return filepath.Join(filepath.Dir(epubPath), "cover.jpg")
}