/*
** Job Arranger for ZABBIX
** Copyright (C) 2025 Daiwa Institute of Research Ltd. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

package zabbixloader

import (
	"errors"
	"fmt"
	"path/filepath"
	"plugin"
	"sync"

	zbxlink "jobarranger2/src/jobarg_server/managers/zabbix_link_manager/zbx_link"
	"jobarranger2/src/libs/golibs/common"
	"jobarranger2/src/libs/golibs/database"
)

var (
	zbxUpdater zbxlink.ZabbixUpdater
	loadErr    error
	loadOnce   sync.Once
)

func GetZabbixUpdater(version int, db database.DBConnection) (zbxlink.ZabbixUpdater, error) {
	loadOnce.Do(func() {
		zbxUpdater, loadErr = LoadPluginForZabbixVersion(version, db)
	})
	return zbxUpdater, loadErr
}

func LoadPluginForZabbixVersion(version int, db database.DBConnection) (zbxlink.ZabbixUpdater, error) {
	pluginPath := filepath.Join(common.ZabbixVersionPluginPath, fmt.Sprintf("zabbix_v%d.so", version))

	p, err := plugin.Open(pluginPath)
	if err != nil {
		return nil, fmt.Errorf("fail to open zabbix plugin: %w", err)
	}

	sym, err := p.Lookup("NewUpdater")
	if err != nil {
		return nil, fmt.Errorf("fail to look up: %w", err)
	}

	zbxUpdaterFunc, ok := sym.(func(dbConn database.DBConnection) zbxlink.ZabbixUpdater)
	if !ok {
		return nil, errors.New("invalid plugin signature")
	}

	return zbxUpdaterFunc(db), nil
}
