// Copyright 2017 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.

package catalog

import (
	

	
	
	
)

// TODO:
// Dictionary returns a Dictionary that returns the first Message, using the
// given language tag, that matches:
//   1. the last one registered by one of the Set methods
//   2. returned by one of the Loaders
//   3. repeat from 1. using the parent language
// This approach allows messages to be underspecified.
// func (c *Catalog) Dictionary(tag language.Tag) (Dictionary, error) {
// 	// TODO: verify dictionary exists.
// 	return &dict{&c.index, tag}, nil
// }

type dict struct {
	s   *store
	tag language.Tag // TODO: make compact tag.
}

func ( *dict) ( string) ( string,  bool) {
	return .s.lookup(.tag, )
}

func ( *Builder) ( language.Tag,  string) ( string,  bool) {
	return .index.lookup(, )
}

func ( *Builder) ( language.Tag,  string,  *store,  ...Message) error {
	,  := catmsg.Compile(, &dict{&.macros, }, firstInSequence())

	.mutex.Lock()
	defer .mutex.Unlock()

	 := .index[]
	if  == nil {
		 = msgMap{}
		if .index == nil {
			.index = map[language.Tag]msgMap{}
		}
		.matcher = nil
		.index[] = 
	}

	[] = 
	return 
}

func ( *Builder) () language.Matcher {
	.index.mutex.RLock()
	 := .matcher
	.index.mutex.RUnlock()
	if  != nil {
		return 
	}

	.index.mutex.Lock()
	if .matcher == nil {
		.matcher = language.NewMatcher(.unlockedLanguages())
	}
	 = .matcher
	.index.mutex.Unlock()
	return 
}

type store struct {
	mutex sync.RWMutex
	index map[language.Tag]msgMap
}

type msgMap map[string]string

func ( *store) ( language.Tag,  string) ( string,  bool) {
	.mutex.RLock()
	defer .mutex.RUnlock()

	for ; ;  = .Parent() {
		if ,  := .index[];  {
			if ,  := [];  {
				return , true
			}
		}
		if  == language.Und {
			break
		}
	}
	return "", false
}

// Languages returns all languages for which the Catalog contains variants.
func ( *Builder) () []language.Tag {
	 := &.index
	.mutex.RLock()
	defer .mutex.RUnlock()

	return .unlockedLanguages()
}

func ( *Builder) () []language.Tag {
	 := &.index
	if len(.index) == 0 {
		return nil
	}
	 := make([]language.Tag, 0, len(.index))
	,  := .index[.options.fallback]
	 := 0
	if  {
		 = append(, .options.fallback)
		 = 1
	}
	for  := range .index {
		if  != .options.fallback {
			 = append(, )
		}
	}
	internal.SortTags([:])
	return 
}