// Copyright 2013 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 or at
// https://developers.google.com/open-source/licenses/bsd.

package gosrc

import (
	"regexp"
	"time"
)

type Presentation struct {
	Filename string
	Files    map[string][]byte
	Updated  time.Time
}

type presBuilder struct {
	filename   string
	data       []byte
	resolveURL func(fname string) string
	fetch      func(fnames []string) ([]*File, error)
}

var assetPat = regexp.MustCompile(`(?m)^\.(play|code|image|iframe|html)\s+(?:-\S+\s+)*(\S+)`)

func (b *presBuilder) build() (*Presentation, error) {
	var data []byte
	var fnames []string
	i := 0
	for _, m := range assetPat.FindAllSubmatchIndex(b.data, -1) {
		name := string(b.data[m[4]:m[5]])
		switch string(b.data[m[2]:m[3]]) {
		case "iframe", "image":
			data = append(data, b.data[i:m[4]]...)
			data = append(data, b.resolveURL(name)...)
		case "html":
			// TODO: sanitize and fix relative URLs in HTML.
			data = append(data, "\nERROR: .html not supported\n"...)
		case "play", "code":
			data = append(data, b.data[i:m[5]]...)
			found := false
			for _, n := range fnames {
				if n == name {
					found = true
					break
				}
			}
			if !found {
				fnames = append(fnames, name)
			}
		default:
			data = append(data, "\nERROR: unknown command\n"...)
		}
		i = m[5]
	}
	data = append(data, b.data[i:]...)
	files, err := b.fetch(fnames)
	if err != nil {
		return nil, err
	}
	pres := &Presentation{
		Updated:  time.Now().UTC(),
		Filename: b.filename,
		Files:    map[string][]byte{b.filename: data},
	}
	for _, f := range files {
		pres.Files[f.Name] = f.Data
	}
	return pres, nil
}
