package apidApigeeSync

import (
	"github.com/30x/apid-core"
	"github.com/apigee-labs/transicator/common"
)

const (
	LISTENER_TABLE_APID_CLUSTER = "edgex.apid_cluster"
	LISTENER_TABLE_DATA_SCOPE   = "edgex.data_scope"
)

type handler struct {
}

func (h *handler) String() string {
	return "ApigeeSync"
}

func (h *handler) Handle(e apid.Event) {

	if changeSet, ok := e.(*common.ChangeList); ok {
		processChangeList(changeSet)
	} else if snapShot, ok := e.(*common.Snapshot); ok {
		processSnapshot(snapShot)
	} else {
		log.Errorf("Received invalid event. Ignoring. %v", e)
	}
}

func processSnapshot(snapshot *common.Snapshot) {

	log.Debugf("Snapshot received. Switching to DB version: %s", snapshot.SnapshotInfo)

	db, err := data.DBVersion(snapshot.SnapshotInfo)
	if err != nil {
		log.Panicf("Unable to access database: %v", err)
	}

	err = initDB(db)
	if err != nil {
		log.Panicf("Unable to initialize database: %v", err)
	}

	// clear cache
	scopeCache.clearAndInitCache(snapshot.SnapshotInfo)

	tx, err := db.Begin()
	if err != nil {
		log.Panicf("Error starting transaction: %v", err)
	}
	defer tx.Rollback()

	for _, table := range snapshot.Tables {

		switch table.Name {
		case LISTENER_TABLE_APID_CLUSTER:
			if len(table.Rows) > 1 {
				log.Panic("Illegal state for apid_cluster. Must be a single row.")
			}
			for _, row := range table.Rows {
				ac := makeApidClusterFromRow(row)
				err := insertApidCluster(ac, tx)
				if err != nil {
					log.Panicf("Snapshot update failed: %v", err)
				}
			}

		case LISTENER_TABLE_DATA_SCOPE:
			for _, row := range table.Rows {
				ds := makeDataScopeFromRow(row)
				err := insertDataScope(ds, tx)
				if err != nil {
					log.Panicf("Snapshot update failed: %v", err)
				}
				// cache scopes for this cluster
				if ds.ClusterID == apidInfo.ClusterID {
					scopeCache.updateCache(&ds)
				}
			}
		}
	}

	err = tx.Commit()
	if err != nil {
		log.Panicf("Error committing Snapshot change: %v", err)
	}

	apidInfo.LastSnapshot = snapshot.SnapshotInfo
	err = updateApidInstanceInfo()
	if err != nil {
		log.Panicf("Unable to update instance info: %v", err)
	}

	setDB(db)
	log.Debugf("Snapshot processed: %s", snapshot.SnapshotInfo)
}

func processChangeList(changes *common.ChangeList) {

	tx, err := getDB().Begin()
	if err != nil {
		log.Panicf("Error processing ChangeList: %v", err)
	}
	defer tx.Rollback()

	log.Debugf("apigeeSyncEvent: %d changes", len(changes.Changes))

	for _, change := range changes.Changes {
		switch change.Table {
		case "edgex.apid_cluster":
			switch change.Operation {
			case common.Delete:
				// todo: shut down apid, delete databases, scorch the earth!
				log.Panicf("illegal operation: %s for %s", change.Operation, change.Table)
			default:
				log.Panicf("illegal operation: %s for %s", change.Operation, change.Table)
			}
		case "edgex.data_scope":
			switch change.Operation {
			case common.Insert:
				ds := makeDataScopeFromRow(change.NewRow)
				err = insertDataScope(ds, tx)

				// cache scopes for this cluster
				if (ds.ClusterID == apidInfo.ClusterID) && (err == nil) {
					scopeCache.updateCache(&ds)
				}
			case common.Delete:
				ds := makeDataScopeFromRow(change.OldRow)
				err = deleteDataScope(ds, tx)

				// cache scopes for this cluster
				if (ds.ClusterID == apidInfo.ClusterID) && (err == nil) {
					scopeCache.removeCache(&ds)
				}
			default:
				// common.Update is not allowed
				log.Panicf("illegal operation: %s for %s", change.Operation, change.Table)
			}
		}
		if err != nil {
			log.Panicf("Error processing ChangeList: %v", err)
		}
	}

	err = tx.Commit()
	if err != nil {
		log.Panicf("Error processing ChangeList: %v", err)
	}
}

func makeApidClusterFromRow(row common.Row) dataApidCluster {

	dac := dataApidCluster{}

	row.Get("id", &dac.ID)
	row.Get("name", &dac.Name)
	row.Get("umbrella_org_app_name", &dac.OrgAppName)
	row.Get("created", &dac.Created)
	row.Get("created_by", &dac.CreatedBy)
	row.Get("updated", &dac.Updated)
	row.Get("updated_by", &dac.UpdatedBy)
	row.Get("description", &dac.Description)

	return dac
}

func makeDataScopeFromRow(row common.Row) dataDataScope {

	ds := dataDataScope{}

	row.Get("id", &ds.ID)
	row.Get("apid_cluster_id", &ds.ClusterID)
	row.Get("scope", &ds.Scope)
	row.Get("org", &ds.Org)
	row.Get("env", &ds.Env)
	row.Get("created", &ds.Created)
	row.Get("created_by", &ds.CreatedBy)
	row.Get("updated", &ds.Updated)
	row.Get("updated_by", &ds.UpdatedBy)

	return ds
}
