package arrange

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"time"
)

// Media is the high-level filetype that can be arranged.
type Media struct {
	Path      string
	Hash      string
	Extension string
	Time      time.Time
}

// Move is called to push Media into its final destination, by content address
// and by date.
func (m Media) Move(root string) error {
	f, err := os.Open(m.Path)
	if err != nil {
		return fmt.Errorf("problem opening file %q: %v", m.Path, err)
	}
	defer f.Close()

	content := m.Content(root)

	if _, err := os.Stat(content); !os.IsNotExist(err) {
		return Dup{content}
	}

	out, err := os.Create(content)
	if err != nil {
		return fmt.Errorf("could not create output file: %v", err)
	}
	defer out.Close()

	if _, err := io.Copy(out, f); err != nil {
		return fmt.Errorf("trouble copying file: %v", err)
	}

	if err := os.Chtimes(content, time.Now(), m.Time); err != nil {
		return fmt.Errorf("couldn't chtimes for %q: %v", content, err)
	}

	year := fmt.Sprintf("%04d", m.Time.Year())
	month := fmt.Sprintf("%02d", m.Time.Month())
	ts := fmt.Sprintf("%d", m.Time.UnixNano())

	if err := os.MkdirAll(filepath.Join(root, "date", year, month), 0755); err != nil {
		return fmt.Errorf("problem creating date directory: %v", err)
	}

	date := filepath.Join(root, "date", year, month, ts)
	name := date + m.Extension
	for i := 0; i < 10000; i++ {
		if _, err := os.Stat(name); os.IsNotExist(err) {
			break
		}
		name = fmt.Sprintf("%s_%04d%s", date, i, m.Extension)
	}

	// TODO: or maybe symlinking? (issue #2)
	// rel := filepath.Join("..", "..", "..", "content", j.hash[:2], j.hash[2:]+m.Extension)
	// return os.Symlink(rel, name)
	return os.Link(content, name)
}

// Content returns the content-address path starting at root.
func (m Media) Content(root string) string {
	return filepath.Join(root, "content", m.Hash[:2], m.Hash[2:]+m.Extension)
}
