// ldap
package util

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"strings"

	"github.com/nmcclain/ldap"
)

type pwdStor string

func (p pwdStor) GetSaltedSha1() string {
	source := strings.TrimSpace(string(p))
	Log().Errorf("source %s", source)

	var err error
	salt := make([]byte, 4)

	_, err = rand.Read(salt)

	if err != nil {
		panic(err)
	}

	hasher := sha1.New()

	hasher.Write([]byte(source))

	if err != nil {
		panic(err)
	}

	hasher.Write(salt)

	if err != nil {
		panic(err)
	}

	encoded := base64.StdEncoding.EncodeToString(append(hasher.Sum(nil), salt...))
	tag := "{SSHA}"

	formatted := tag + encoded
	Log().Errorf("sha1 %s", formatted)
	return formatted
}

type ldapUnit struct {
	dn                  string
	filter              string
	uniqueAttributeName string
}

type ldapSource struct {
	host       string
	port       int16
	user       ldapUnit
	group      ldapUnit
	connection *ldap.Conn
}

type AccountSource interface {
	Connect()
	Bind(uid string, password pwdStor)
	Search()
	Close()
}

//ldapSourceBool
func (l *ldapSource) Connect() {
	l.Bind("test", "testpw")
	addr := fmt.Sprintf("%s:%d", l.host, l.port)
	conn, err := ldap.DialTLS("tcp", addr, nil)
	if err == nil {
		//		(*conn).Debug = true
		l.connection = conn
	} else {
		Log().Error(err.Error())
		panic(err)
	}
}

func (l *ldapSource) Close() {
	if l.connection != nil {
		l.connection.Close()
		l.connection = nil
	}
}

func (l ldapSource) Search() {

	search := ldap.NewSearchRequest(
		l.user.dn,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		l.user.filter,
		nil,
		nil)
	searchResults, err := l.connection.Search(search)

	if err == nil {
		for _, v := range searchResults.Entries {

			m := make(map[string][]string)
			for _, attr := range v.Attributes {
				m[attr.Name] = append(m[attr.Name], attr.Values...)
			}
			Log().Error(m)
		}
	} else {
		Log().Error(err.Error())
		panic(err)
	}
}

func (l ldapSource) Bind(uid string, password pwdStor) {
	password.GetSaltedSha1()
}

func NewAccoauntSource() AccountSource {
	user := ldapUnit{
		dn:                  "ou=User,dc=amuz,dc=es",
		filter:              "(objectClass=person)",
		uniqueAttributeName: "uid"}
	group := ldapUnit{
		dn:                  "ou=Group,dc=amuz,dc=es",
		filter:              "|((objectClass=groupOfNames)(objectClass=groupOfUniqueNames))",
		uniqueAttributeName: "cn"}
	return &ldapSource{
		host:  "keeper.amuz.es",
		port:  636,
		user:  user,
		group: group}

}
