// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
// appearance 包用于管理桌面外观设置，包括主题、壁纸、字体等相关功能。
// 该包通过 D-Bus 提供服务，允许外部模块对外观进行统一管理和同步。
//
// 本文件为 appearance 包的主入口，定义了模块初始化、启动、停止等核心逻辑。
package appearance

import (
	"errors"
	"time"

	"github.com/godbus/dbus"
	"github.com/linuxdeepin/go-lib/dbusutil"
	"github.com/linuxdeepin/go-lib/log"

	"github.com/linuxdeepin/dde-daemon/appearance/background"
	"github.com/linuxdeepin/dde-daemon/loader"
)

var (
	// _m 是全局唯一的 Manager 实例，负责管理外观相关的所有状态和操作。
	_m     *Manager
	// logger 用于记录 appearance 模块的日志。
	logger = log.NewLogger("daemon/appearance")
)

// Module 结构体表示 appearance 模块，嵌入 loader.ModuleBase 以实现统一的模块管理接口。
type Module struct {
	*loader.ModuleBase
}

// init 函数在包初始化时调用，设置 background 包的日志器并注册 appearance 模块。
func init() {
	background.SetLogger(logger)
	loader.Register(NewModule(logger))
}

// NewModule 创建一个新的 appearance 模块实例。
// logger: 日志记录器。
// 返回值: *Module 新的模块实例。
func NewModule(logger *log.Logger) *Module {
	var d = new(Module)
	d.ModuleBase = loader.NewModuleBase("appearance", d, logger)
	return d
}

// HandlePrepareForSleep 处理系统休眠/唤醒事件。
// sleep: true 表示进入休眠，false 表示唤醒。
// 唤醒时会根据壁纸轮播配置自动切换壁纸。
func HandlePrepareForSleep(sleep bool) {
	if _m == nil {
		return
	}
	if sleep {
		return
	}
	cfg, err := doUnmarshalWallpaperSlideshow(_m.WallpaperSlideShow.Get())
	if err == nil {
		for monitorSpace := range cfg {
			if cfg[monitorSpace] == wsPolicyWakeup {
				_m.autoChangeBg(monitorSpace, time.Now())
			}
		}
	}
}

// GetDependencies 返回 appearance 模块的依赖模块列表。
// appearance 模块无依赖，返回空列表。
func (*Module) GetDependencies() []string {
	return []string{}
}

// start 启动 appearance 模块，初始化 Manager 并导出 D-Bus 服务。
// 返回值: error 启动失败时返回错误。
func (*Module) start() error {
	service := loader.GetService()

	_m = newManager(service)
	err := _m.init()
	if err != nil {
		logger.Warning(err)
		return err
	}

	err = service.Export(dbusPath, _m, _m.syncConfig)
	if err != nil {
		_m.destroy()
		return err
	}

	err = service.Export(backgroundDBusPath, _m.bgSyncConfig)
	if err != nil {
		return err
	}

	so := service.GetServerObject(_m)
	err = so.SetWriteCallback(_m, propQtActiveColor, func(write *dbusutil.PropertyWrite) *dbus.Error {
		value, ok := write.Value.(string)
		if !ok {
			return dbusutil.ToError(errors.New("type is not string"))
		}
		err = _m.setQtActiveColor(value)
		return dbusutil.ToError(err)
	})
	if err != nil {
		return err
	}

	err = service.RequestName(dbusServiceName)
	if err != nil {
		_m.destroy()
		err = service.StopExport(_m)
		if err != nil {
			return err
		}
		return err
	}

	err = _m.syncConfig.Register()
	if err != nil {
		logger.Warning("failed to register for deepin sync", err)
	}

	err = _m.bgSyncConfig.Register()
	if err != nil {
		logger.Warning("failed to register for deepin sync", err)
	}

	go _m.listenCursorChanged()
	go _m.handleThemeChanged()
	_m.listenGSettingChanged()
	_m.initFont()
	return nil
}

// Start 启动 appearance 模块。
// 若已启动则直接返回。
func (m *Module) Start() error {
	if _m != nil {
		return nil
	}
	return m.start()
}

// Stop 停止 appearance 模块，销毁 Manager 并注销 D-Bus 服务。
func (*Module) Stop() error {
	if _m == nil {
		return nil
	}

	_m.destroy()
	service := loader.GetService()
	err := service.StopExport(_m)
	if err != nil {
		return err
	}
	_m = nil
	return nil
}
