// Copyright 2014 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 language

import (
	
	

	
)

// The Coverage interface is used to define the level of coverage of an
// internationalization service. Note that not all types are supported by all
// services. As lists may be generated on the fly, it is recommended that users
// of a Coverage cache the results.
type Coverage interface {
	// Tags returns the list of supported tags.
	Tags() []Tag

	// BaseLanguages returns the list of supported base languages.
	BaseLanguages() []Base

	// Scripts returns the list of supported scripts.
	Scripts() []Script

	// Regions returns the list of supported regions.
	Regions() []Region
}

var (
	// Supported defines a Coverage that lists all supported subtags. Tags
	// always returns nil.
	Supported Coverage = allSubtags{}
)

// TODO:
// - Support Variants, numbering systems.
// - CLDR coverage levels.
// - Set of common tags defined in this package.

type allSubtags struct{}

// Regions returns the list of supported regions. As all regions are in a
// consecutive range, it simply returns a slice of numbers in increasing order.
// The "undefined" region is not returned.
func ( allSubtags) () []Region {
	 := make([]Region, language.NumRegions)
	for  := range  {
		[] = Region{language.Region( + 1)}
	}
	return 
}

// Scripts returns the list of supported scripts. As all scripts are in a
// consecutive range, it simply returns a slice of numbers in increasing order.
// The "undefined" script is not returned.
func ( allSubtags) () []Script {
	 := make([]Script, language.NumScripts)
	for  := range  {
		[] = Script{language.Script( + 1)}
	}
	return 
}

// BaseLanguages returns the list of all supported base languages. It generates
// the list by traversing the internal structures.
func ( allSubtags) () []Base {
	 := language.BaseLanguages()
	 := make([]Base, len())
	for ,  := range  {
		[] = Base{}
	}
	return 
}

// Tags always returns nil.
func ( allSubtags) () []Tag {
	return nil
}

// coverage is used by NewCoverage which is used as a convenient way for
// creating Coverage implementations for partially defined data. Very often a
// package will only need to define a subset of slices. coverage provides a
// convenient way to do this. Moreover, packages using NewCoverage, instead of
// their own implementation, will not break if later new slice types are added.
type coverage struct {
	tags    func() []Tag
	bases   func() []Base
	scripts func() []Script
	regions func() []Region
}

func ( *coverage) () []Tag {
	if .tags == nil {
		return nil
	}
	return .tags()
}

// bases implements sort.Interface and is used to sort base languages.
type bases []Base

func ( bases) () int {
	return len()
}

func ( bases) (,  int) {
	[], [] = [], []
}

func ( bases) (,  int) bool {
	return [].langID < [].langID
}

// BaseLanguages returns the result from calling s.bases if it is specified or
// otherwise derives the set of supported base languages from tags.
func ( *coverage) () []Base {
	if .bases == nil {
		 := .Tags()
		if len() == 0 {
			return nil
		}
		 := make([]Base, len())
		for ,  := range  {
			[] = Base{language.Language(.lang())}
		}
		sort.Sort(bases())
		 := 0
		for  := 1;  < len(); ++ {
			if [] != [] {
				++
				[] = []
			}
		}
		return [:+1]
	}
	return .bases()
}

func ( *coverage) () []Script {
	if .scripts == nil {
		return nil
	}
	return .scripts()
}

func ( *coverage) () []Region {
	if .regions == nil {
		return nil
	}
	return .regions()
}

// NewCoverage returns a Coverage for the given lists. It is typically used by
// packages providing internationalization services to define their level of
// coverage. A list may be of type []T or func() []T, where T is either Tag,
// Base, Script or Region. The returned Coverage derives the value for Bases
// from Tags if no func or slice for []Base is specified. For other unspecified
// types the returned Coverage will return nil for the respective methods.
func ( ...interface{}) Coverage {
	 := &coverage{}
	for ,  := range  {
		switch v := .(type) {
		case func() []Base:
			.bases = 
		case func() []Script:
			.scripts = 
		case func() []Region:
			.regions = 
		case func() []Tag:
			.tags = 
		case []Base:
			.bases = func() []Base { return  }
		case []Script:
			.scripts = func() []Script { return  }
		case []Region:
			.regions = func() []Region { return  }
		case []Tag:
			.tags = func() []Tag { return  }
		default:
			panic(fmt.Sprintf("language: unsupported set type %T", ))
		}
	}
	return 
}