package deliberi

import "tangled.org/core/deliberi/models"

// api/org_tangled has no bindings for these records yet, so decode only the
// fields the ingester reads
const (
	repoManifestNSID = "org.tangled.repo.manifest"
	ticketNSID       = "org.tangled.track.ticket"
	commentNSID      = "org.tangled.feed.comment"
	starNSID         = "org.tangled.feed.star"
	followNSID       = "org.tangled.graph.follow"
	collaboratorNSID = "org.tangled.graph.collaborator"
	subscriptionNSID = "org.tangled.feed.subscription"
	patchNSID        = "org.tangled.review.patch"

	starRepoType = "org.tangled.feed.star#repo"

	ticketStateOpen      = "open"
	ticketStateClosed    = "closed"
	ticketStateCompleted = "completed"
)

type markdownText struct {
	Text string `json:"text"`
}

type repoDeclaration struct {
	Owner string `json:"owner"`
	Name  string `json:"name"`
}

type repoManifest struct {
	Declaration *repoDeclaration `json:"declaration"`
}

// repo-owned records (tickets, comments) live in the repo's account; the knot
// stamps the writing user into x-tngl-editor
type ticketRecord struct {
	State        string        `json:"state"`
	Title        *markdownText `json:"title"`
	Body         *markdownText `json:"body"`
	TargetBranch *string       `json:"targetBranch"`
	Editor       string        `json:"x-tngl-editor"`
}

func (t *ticketRecord) kind() models.EntityKind {
	if t.TargetBranch != nil {
		return models.EntityKindPull
	}
	return models.EntityKindIssue
}

// the knot leaves state off when a ticket is open
func (t *ticketRecord) state() string {
	if t.State == "" {
		return ticketStateOpen
	}
	return t.State
}

func (t *ticketRecord) title() string {
	if t.Title == nil {
		return ""
	}
	return t.Title.Text
}

type commentRecord struct {
	Subject *struct {
		Uri string `json:"uri"`
	} `json:"subject"`
	ReplyTo *struct {
		Uri string `json:"uri"`
	} `json:"replyTo"`
	Body   *markdownText `json:"body"`
	Editor string        `json:"x-tngl-editor"`
}

type patchRecord struct {
	Ticket string `json:"ticket"`
}

type subscriptionRecord struct {
	Subject *struct {
		Uri string `json:"uri"`
		Did string `json:"did"`
	} `json:"subject"`
	Ignore bool `json:"ignore"`
}

func (s *subscriptionRecord) subject() string {
	if s.Subject == nil {
		return ""
	}
	if s.Subject.Uri != "" {
		return s.Subject.Uri
	}
	return s.Subject.Did
}

type starRecord struct {
	Subject *struct {
		Type     string `json:"$type"`
		Identity string `json:"identity"`
	} `json:"subject"`
}

func bodyText(m *markdownText) string {
	if m == nil {
		return ""
	}
	return m.Text
}

// matches bobbin: a record without an editor is attributed to the repo
func editorOr(editor, repoDid string) string {
	if editor == "" {
		return repoDid
	}
	return editor
}
