package main

import (
	"fmt"
	"time"

	cfg "github.com/jesusperez/cfgsrv"
	utils "github.com/jesusperez/datautils"
	log "github.com/sirupsen/logrus"
	"gopkg.in/yaml.v2"
)
func loadUsersData(usersPath string) (map[string]Account, error) {
	var usersData map[string]Account
	d,file,errpath := decoderFromFile(usersPath)
	if errpath != nil {
		return nil, errpath
	}
	defer file.Close()
	if err := d.Decode(&usersData); err != nil {
		log.Fatalf("Decode: %v", err)
		return nil, err
	}
	return usersData, nil
}
func loadUsersAccounts(usersPath string) (*UsersAccounts, error) {
	accounts,err := loadUsersData(usersPath) 
	if err != nil {
		return nil, err
	}
	keyAccounts := accounts	
	for key, user := range accounts {
		user.Id = key
		keyAccounts[key] = user
		if len(user.Email) > 0 {
			accounts[user.Email] = user
		}
	}
	users := &UsersAccounts{
		Accounts: accounts,
	}
	return users, nil
}
func loadWebAccounts(users *UsersAccounts) (*WebAccounts) {
	webusers := &WebAccounts{}
	for key, user := range users.Accounts {
		if user.Web {
			webusers.Accounts[key] = user.Passwd
		}
	}
	return webusers
}
func loadModelsUsers(modelsPath string) (map[string]ModelUser, error) {
	var mdlsUsers map[string]ModelUser
	d,file,errpath := decoderFromFile(modelsPath)
	if errpath != nil {
		return nil, errpath
	}
	defer file.Close()
	if err := d.Decode(&mdlsUsers); err != nil {
		log.Fatalf("Decode: %v", err)
		return nil, err
	}
	// fmt.Printf("users: %+v\n", users)
	return mdlsUsers, nil
}
func checkUserInvitation(key string,invitation Invitation, num int) (Invitation,bool,bool) {
	userInvitation := invitation
	needSync := false
	valid := true
	if invitation.Howmany > -1 && num > 0 {
		needSync = true
		userInvitation.Howmany = invitation.Howmany - num
		if userInvitation.Howmany < 0 {
			userInvitation.Howmany = 0	
			userInvitation.Active = false
			valid = false
		}
	}
	if len(invitation.Expire) > 0 {
		res,err := time.Parse(time.RFC3339,invitation.Expire)
    if err == nil {
			if res.Before(time.Now()) {
				needSync = true   	
				userInvitation.Active = false	
				valid = false
			} 
		} else {
			fmt.Printf("Error parse invitation %s expire %s: %v",key,invitation.Expire,err)	
		}
	}
	return userInvitation,valid,needSync
}
func checkUsersInvitations(invitations map[string]Invitation,writeSync bool,invitationsPath string) map[string]Invitation {
	usersInvitations := map[string]Invitation{}
	savedInvitations := invitations
	needSync := false
	for key, item := range invitations {
		if item.Active {
			invitation,valid,itemSync := checkUserInvitation(key,item,0)
			if (itemSync && !needSync) {
				needSync = true
				savedInvitations[key] = invitation
			} 
			if (valid) {
				usersInvitations[key] = invitation
			}
		}
	}
	if (writeSync && needSync) {
		strdata, yamlerr := yaml.Marshal(savedInvitations)
		if yamlerr != nil {
			fmt.Printf("Error parse invitations: %v",yamlerr)
		} else {
			if res := utils.WriteData(string(strdata),invitationsPath) ; res != nil {    
				fmt.Printf("Error write invitations: %v",res)
			}
		}
	}
	return usersInvitations
}
func loadUsersInvitations(invitationsPath string) (map[string]Invitation, error) {
	var invitations map[string]Invitation
	d,file,errpath := decoderFromFile(invitationsPath)
	if errpath != nil {
		return nil, errpath
	}
	defer file.Close()
	if err := d.Decode(&invitations); err != nil {
		log.Fatalf("Decode: %v", err)
		return nil, err
	}
	return invitations, nil
}  
func getUsersInvitations(invitationsPath string,writeSync bool) (map[string]Invitation, error) {
	invitations,err := loadUsersInvitations(invitationsPath)
	if err != nil {
		fmt.Printf("Error load invitations: %v",err)
		return nil,err
	}
	return checkUsersInvitations(invitations,writeSync,invitationsPath), nil
}
func loadConfig(path string) (*cfg.Config, error) {
	config := &cfg.Config{}
	// fmt.Printf("Loaded config: %#v\n", path)
	// if  yamlFile, err := ioutil.ReadFile(path); err == nil {
	//   err = yaml.Unmarshal(yamlFile, config)
	//   if err != nil {
	// 	   log.Fatalf("Unmarshal: %v", err)
  //   }
	// }
  // var data interface{} = config
	d,file,errpath := decoderFromFile(path)
	if errpath != nil {
		return nil, errpath
	}
	defer file.Close()
	if err := d.Decode(&config); err != nil {
		return nil, err
	}
	if len(config.MailPswd) > 0 {
		txtdata,err := decrypt(config.MailPswd, string(CRYPTKEY))
		if err == nil {
			config.MailPswd = txtdata
		}
	}
	return config, nil
}
func newDataConfig(runFlags RunFlags) (*cfg.Config, error) {
	config,err := loadConfig(runFlags.cfgPath)
	if err != nil {
		log.Fatalf("Decode: %v", err)
		return nil, err
	}
	DEBUGLEVEL = config.DebugLevel
	return config, nil
}

func loadDataConfig(runFlags RunFlags) (*cfg.Config, error) {
	cfg, err := newDataConfig(runFlags)
	if err != nil {
		log.Fatalf("Load data config: %v", err)
		return cfg, err
	}
	return cfg, nil
}

func loadcertkey(runFlags RunFlags) {
	var err error
	CRYPTKEY, err = loadPath(runFlags.keyPath)
	if err != nil {
		log.Fatalf("Error load key: %v", err)
	}
}