package provision

import "C"
import (
	"fmt"
	"github.com/ircop/tclient"
	"proxy/MsgDef"
	"proxy/Nmysql"
	rds "proxy/Nredis"
	l4g "proxy/logger"
	"strconv"
	"strings"
	"time"

	. "proxy/config"
)

func ProvisionFsm() {
	prov := &Config.Provision
	if !prov.Enabled {
		return
	}

	interval := prov.Interval
	if interval <= 0 {
		interval = 8
	}
	ticker := time.NewTicker(time.Second * time.Duration(interval))
	defer ticker.Stop()
	for {
		<-ticker.C // wait for next tick

		CheckNewProvision()
		ProvisionBySmcli()
	}
}

func TelnetClient() {
	client := tclient.New(5, "manager", "manager", "")
	err := client.Open("192.168.13.117", 4999)
	if err != nil {
		panic(err)
	}
	defer client.Close()

	// you can omit this, or do auth stuff manually by calling `ReadUntil` with login/password prompts
	/*out, err := client.Login("manager", "manager")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)*/

	out, err := client.Cmd("connect hlr -srvip 192.168.13.118 -passwd 123456")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)

	out, err = client.Cmd("connect auc -srvip 192.168.13.118 -passwd 123456")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)

	out, err = client.Cmd("connect vms -srvip 192.168.4.221 -passwd 123456")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)

	// smcli cmd

	out, err = client.Cmd("disconnect hlr")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)

	out, err = client.Cmd("disconnect vms")
	if err != nil {
		panic(err)
	}
	fmt.Printf(out)

	//out, err = client.ReadUntil()
}

func CheckNewProvision() {
	si, _ := Nmysql.QuerySyncMobileInfo()
	if si != nil {
		for _, v := range si {
			if v.OperType == 2 {// replace imsi
				oi, _ := Nmysql.QueryOldImsiInfo(v.ServiceNbr)
				if oi != nil {
					Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_DISCONNECT_ACCOUNT, Nmysql.NT_HSS, strconv.Itoa(oi.PrdInstId), "delete subscriber -imsi " + v.Imsi)
					Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_DISCONNECT_ACCOUNT, Nmysql.NT_AUC, strconv.Itoa(oi.PrdInstId),"delete aucSubscriber -imsi " + v.Imsi)
					Nmysql.UpdateSyncMobileState(oi.PreId, 6)

					crtCmd := fmt.Sprintf("create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
						v.Imsi, v.ServiceNbr, v.Imsi)
					Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_HSS, strconv.Itoa(v.PrdInstId), crtCmd)

					if v.Opc == "" {
						crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s",
							v.Imsi, v.Ki)
					} else {
						crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s -opc %s",
							v.Imsi, v.Ki, v.Opc)
					}
					Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_AUC, strconv.Itoa(v.PrdInstId), crtCmd)
					Nmysql.UpdateSyncMobileState(v.PreId, 2)
				}
			} else {
				crtCmd := fmt.Sprintf("create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
					v.Imsi, v.ServiceNbr, v.Imsi)
				Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_HSS, strconv.Itoa(v.PrdInstId), crtCmd)

				if v.Opc == "" {
					crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s",
						v.Imsi, v.Ki)
				} else {
					crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s -opc %s",
						v.Imsi, v.Ki, v.Opc)
				}
				Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_AUC, strconv.Itoa(v.PrdInstId), crtCmd)

				if v.VmsFlag > 0 {
					crtCmd := fmt.Sprintf("create vmsSubscriber -msisdn %s",
						v.ServiceNbr)
					Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_VMS, strconv.Itoa(v.PrdInstId), crtCmd)
				}

				// add ocs success
				crtCmd = fmt.Sprintf("create ppsSubscriber -msisdn %s -PRE_ID %d",
					v.ServiceNbr, v.PreId)
				Nmysql.AddSmcliCmdSucc2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_OCS, strconv.Itoa(v.PrdInstId), crtCmd)
				var synMobile = MsgDef.ChgSyncMobile{PreId: v.PreId, OperType: v.OperType, State: 1, ServiceNbr: v.ServiceNbr, CustId: v.CustId, AcctId: v.AcctId,
					PrdInstId: v.PrdInstId, MobileType: v.MobileType, BirthDate: v.BirthDate, Balance: v.Balance, BalanceExpDate: v.BalanceExpDate, OfrId: v.OfrId,
					Imsi: v.Imsi, Ki: v.Ki, Opc: v.Opc, VmsFlag: v.VmsFlag, ExpDate: v.ExpDate, CugId: v.CugId}
				rds.RdbSetCreateAcctRecord(&synMobile)

				Nmysql.UpdateSyncMobileState(v.PreId, 2)
			}
		}
	}
}

func ProvisionBySmcli() {
	si, _ := Nmysql.QuerySyncCnCmd()
	if si != nil {
		prv := &Config.Provision
		SmcliClient := tclient.New(prv.ReadTimout, prv.Username, prv.Password, "")
		err := SmcliClient.Open(prv.EmsIp, prv.EmsPort)
		if err != nil {
			l4g.ProvLog.Errorf("Smcli Client Open fail: %v", err)
			return
		}
		defer SmcliClient.Close()

		var out string
		if prv.ConnectHss != "" {
			out, err = SmcliClient.Cmd(prv.ConnectHss)
			if err != nil {
				l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectHss, err)
				return
			}
			l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectHss, out)
			if !strings.Contains(out, "success") {// 0000:Command successful
				l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectHss)
				return
			}
		}

		if prv.ConnectAuc != "" {
			out, err = SmcliClient.Cmd(prv.ConnectAuc)
			if err != nil {
				l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectAuc, err)
				goto ReleaseConnnet
			}
			l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectAuc, out)
			if !strings.Contains(out, "success") {// 0000:Command successful
				l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectAuc)
				goto ReleaseConnnet
			}
		}

		if prv.ConnectVms != "" {
			out, err = SmcliClient.Cmd(prv.ConnectVms)
			if err != nil {
				l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectVms, err)
				goto ReleaseConnHss
			}
			l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectVms, out)
			if !strings.Contains(out, "success") {// 0000:Command successful
				l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectVms)
				goto ReleaseConnHss
			}
		}

		// smcli cmd
		for _, v := range si {
			if v.Command != "" {
				out, err = SmcliClient.Cmd(v.Command)
				if err != nil {
					l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", v.Command, err)
					Nmysql.UpdateCnCmdResult(v.Id, 2, 2, "timeout")
					goto ReleaseConnnet
				}
				l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", v.Command, out)
				if !strings.Contains(out, "success") {// 0000:Command successful
					l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", v.Command)
					Nmysql.UpdateCnCmdResult(v.Id, 2, 2, out)
					goto ReleaseConnnet
				} else {
					l4g.ProvLog.Infof("Smcli Cmd[%s] success", v.Command)
					Nmysql.UpdateCnCmdResult(v.Id, 2, 1, out)
				}
			}
		}

ReleaseConnnet:
		if prv.DisconnectVms != "" {
			out, err = SmcliClient.Cmd(prv.DisconnectVms)
			if err != nil {
				l4g.ProvLog.Errorf("Smcli Client Cmd[%s] fail: %v", prv.DisconnectVms, err)
				return
			}
			l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.DisconnectVms, out)
		}

ReleaseConnHss:
		if prv.DisconnectHss != "" {
			out, err = SmcliClient.Cmd(prv.DisconnectHss)
			if err != nil {
				l4g.ProvLog.Errorf("Smcli Client Cmd[%s] fail: %v", prv.DisconnectHss, err)
				return
			}
			l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.DisconnectHss, out)
		}

	}
}
