package multibase

import (
	
	
	
	

	b58 
	b32 
	b36 
)

// Encoding identifies the type of base-encoding that a multibase is carrying.
type Encoding int

// These are the encodings specified in the standard, not are all
// supported yet
const (
	Identity          = 0x00
	Base2             = '0'
	Base8             = '7'
	Base10            = '9'
	Base16            = 'f'
	Base16Upper       = 'F'
	Base32            = 'b'
	Base32Upper       = 'B'
	Base32pad         = 'c'
	Base32padUpper    = 'C'
	Base32hex         = 'v'
	Base32hexUpper    = 'V'
	Base32hexPad      = 't'
	Base32hexPadUpper = 'T'
	Base36            = 'k'
	Base36Upper       = 'K'
	Base58BTC         = 'z'
	Base58Flickr      = 'Z'
	Base64            = 'm'
	Base64url         = 'u'
	Base64pad         = 'M'
	Base64urlPad      = 'U'
	Base256Emoji      = '🚀'
)

// EncodingToStr is a map of the supported encoding, unsupported encoding
// specified in standard are left out
var EncodingToStr = map[Encoding]string{
	0x00:         "identity",
	'0':          "base2",
	'f':          "base16",
	'F':          "base16upper",
	'b':          "base32",
	'B':          "base32upper",
	'c':          "base32pad",
	'C':          "base32padupper",
	'v':          "base32hex",
	'V':          "base32hexupper",
	't':          "base32hexpad",
	'T':          "base32hexpadupper",
	'k':          "base36",
	'K':          "base36upper",
	'z':          "base58btc",
	'Z':          "base58flickr",
	'm':          "base64",
	'u':          "base64url",
	'M':          "base64pad",
	'U':          "base64urlpad",
	Base256Emoji: "base256emoji",
}

var Encodings = map[string]Encoding{}

func init() {
	for ,  := range EncodingToStr {
		Encodings[] = 
	}
}

// ErrUnsupportedEncoding is returned when the selected encoding is not known or
// implemented.
var ErrUnsupportedEncoding = fmt.Errorf("selected encoding not supported")

// Encode encodes a given byte slice with the selected encoding and returns a
// multibase string (<encoding><base-encoded-string>). It will return
// an error if the selected base is not known.
func ( Encoding,  []byte) (string, error) {
	switch  {
	case Identity:
		// 0x00 inside a string is OK in golang and causes no problems with the length calculation.
		return string(rune(Identity)) + string(), nil
	case Base2:
		return string(Base2) + binaryEncodeToString(), nil
	case Base16:
		return string(Base16) + hex.EncodeToString(), nil
	case Base16Upper:
		return string(Base16Upper) + hexEncodeToStringUpper(), nil
	case Base32:
		return string(Base32) + base32StdLowerNoPad.EncodeToString(), nil
	case Base32Upper:
		return string(Base32Upper) + base32StdUpperNoPad.EncodeToString(), nil
	case Base32hex:
		return string(Base32hex) + base32HexLowerNoPad.EncodeToString(), nil
	case Base32hexUpper:
		return string(Base32hexUpper) + base32HexUpperNoPad.EncodeToString(), nil
	case Base32pad:
		return string(Base32pad) + base32StdLowerPad.EncodeToString(), nil
	case Base32padUpper:
		return string(Base32padUpper) + base32StdUpperPad.EncodeToString(), nil
	case Base32hexPad:
		return string(Base32hexPad) + base32HexLowerPad.EncodeToString(), nil
	case Base32hexPadUpper:
		return string(Base32hexPadUpper) + base32HexUpperPad.EncodeToString(), nil
	case Base36:
		return string(Base36) + b36.EncodeToStringLc(), nil
	case Base36Upper:
		return string(Base36Upper) + b36.EncodeToStringUc(), nil
	case Base58BTC:
		return string(Base58BTC) + b58.EncodeAlphabet(, b58.BTCAlphabet), nil
	case Base58Flickr:
		return string(Base58Flickr) + b58.EncodeAlphabet(, b58.FlickrAlphabet), nil
	case Base64pad:
		return string(Base64pad) + base64.StdEncoding.EncodeToString(), nil
	case Base64urlPad:
		return string(Base64urlPad) + base64.URLEncoding.EncodeToString(), nil
	case Base64url:
		return string(Base64url) + base64.RawURLEncoding.EncodeToString(), nil
	case Base64:
		return string(Base64) + base64.RawStdEncoding.EncodeToString(), nil
	case Base256Emoji:
		return string(Base256Emoji) + base256emojiEncode(), nil
	default:
		return "", ErrUnsupportedEncoding
	}
}

// Decode takes a multibase string and decodes into a bytes buffer.
// It will return an error if the selected base is not known.
func ( string) (Encoding, []byte, error) {
	if len() == 0 {
		return 0, nil, fmt.Errorf("cannot decode multibase for zero length string")
	}

	,  := utf8.DecodeRuneInString()
	 := Encoding()

	switch  {
	case Identity:
		return Identity, []byte([1:]), nil
	case Base2:
		,  := decodeBinaryString([1:])
		return , , 
	case Base16, Base16Upper:
		,  := hex.DecodeString([1:])
		return , , 
	case Base32, Base32Upper:
		,  := b32.RawStdEncoding.DecodeString([1:])
		return , , 
	case Base32hex, Base32hexUpper:
		,  := b32.RawHexEncoding.DecodeString([1:])
		return , , 
	case Base32pad, Base32padUpper:
		,  := b32.StdEncoding.DecodeString([1:])
		return , , 
	case Base32hexPad, Base32hexPadUpper:
		,  := b32.HexEncoding.DecodeString([1:])
		return , , 
	case Base36, Base36Upper:
		,  := b36.DecodeString([1:])
		return , , 
	case Base58BTC:
		,  := b58.DecodeAlphabet([1:], b58.BTCAlphabet)
		return Base58BTC, , 
	case Base58Flickr:
		,  := b58.DecodeAlphabet([1:], b58.FlickrAlphabet)
		return Base58Flickr, , 
	case Base64pad:
		,  := base64.StdEncoding.DecodeString([1:])
		return Base64pad, , 
	case Base64urlPad:
		,  := base64.URLEncoding.DecodeString([1:])
		return Base64urlPad, , 
	case Base64:
		,  := base64.RawStdEncoding.DecodeString([1:])
		return Base64, , 
	case Base64url:
		,  := base64.RawURLEncoding.DecodeString([1:])
		return Base64url, , 
	case Base256Emoji:
		,  := base256emojiDecode([4:])
		return Base256Emoji, , 
	default:
		return -1, nil, ErrUnsupportedEncoding
	}
}