// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

package config

import (
	"encoding/json"
	"errors"
	"os"
	"sync"
	"time"

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

	"github.com/linuxdeepin/lastore-daemon/src/internal/system"
	"github.com/linuxdeepin/lastore-daemon/src/internal/utils"

	"github.com/godbus/dbus/v5"
	ConfigManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager"
)

const MinCheckInterval = time.Minute
const ConfigVersion = "0.1"

// LastoreDaemonStatus 由于lastore-daemon会闲时退出,dde-session-shell和dde-control-center需要获取实时状态时需要从dconfig获取,而不是从lastore-daemon获取
type LastoreDaemonStatus uint32

var logger = log.NewLogger("lastore/config")

// DisableConsoleLogging keeps config logs away from stdout for commands that
// need machine-readable output.
func DisableConsoleLogging() {
	logger.RemoveBackendConsole()
}

const (
	CanUpgrade    LastoreDaemonStatus = 1 << 0 // 是否可以进行安装更新操作
	DisableUpdate LastoreDaemonStatus = 1 << 1 // 当前系统是否禁用了更新
	ForceUpdate   LastoreDaemonStatus = 1 << 2 // 关机强制更新
)

type DisabledStatus uint32

const (
	DisabledUnknown         DisabledStatus = 1 << 0 // 禁用重启后的检查项，1063前的版本不兼容需要禁用 // 该配置项不作为配置生效
	DisabledVersion         DisabledStatus = 1 << 1 // 禁用version请求
	DisabledUpdateLog       DisabledStatus = 1 << 2 // 禁用systemupdatelogs请求
	DisabledTargetPkgLists  DisabledStatus = 1 << 3
	DisabledCurrentPkgLists DisabledStatus = 1 << 4
	DisabledPkgCVEs         DisabledStatus = 1 << 5
	DisabledProcess         DisabledStatus = 1 << 6
	DisabledResult          DisabledStatus = 1 << 7
	DisabledRebootCheck     DisabledStatus = 1 << 8 // 禁用重启后的检查项，1063前的版本不兼容需要禁用
)

type Config struct {
	Version               string
	AutoCheckUpdates      bool
	DisableUpdateMetadata bool
	AutoDownloadUpdates   bool
	AutoClean             bool
	MirrorSource          string
	UpdateNotify          bool
	CheckInterval         time.Duration
	CleanInterval         time.Duration
	UpdateMode            system.UpdateType
	CheckUpdateMode       system.UpdateType
	IncrementalUpdate     bool
	IntranetUpdate        bool

	// 缓存大小超出限制时的清理时间间隔
	CleanIntervalCacheOverLimit    time.Duration
	AppstoreRegion                 string
	LastCheckTime                  time.Time
	LastCleanTime                  time.Time
	LastCheckCacheSizeTime         time.Time
	Repository                     string
	MirrorsUrl                     string
	AllowInstallRemovePkgExecPaths []string
	AutoInstallUpdates             bool
	AutoInstallUpdateType          system.UpdateType

	AllowPostSystemUpgradeMessageVersion []string // 只有数组内的系统版本被允许发送更新完成的数据

	dsLastoreManager   ConfigManager.Manager
	useDSettings       bool
	UpgradeStatus      system.UpgradeStatusAndReason
	IdleDownloadConfig string
	SystemSourceList   []string // 系统更新list文件路径
	SecuritySourceList []string // 安全更新list文件路径
	NonUnknownList     []string // 非未知来源更新list文件
	OtherSourceList    []string // 其他类型更新list文件路径

	DownloadSpeedLimitConfig           string // 下载限速配置
	LocalDownloadSpeedLimitConfig      string
	DeliveryRemoteDownloadGlobalLimit  string
	DeliveryRemoteUploadGlobalLimit    string
	DeliveryRemoteDownloadPeakLimit    string
	DeliveryRemoteUploadPeakLimit      string
	DeliveryRemoteDownloadOffPeakLimit string
	DeliveryRemoteUploadOffPeakLimit   string
	DeliveryLocalDownloadGlobalLimit   string
	DeliveryLocalUploadGlobalLimit     string
	DeliveryLocalDownloadPeakLimit     string
	DeliveryLocalUploadPeakLimit       string
	DeliveryLocalDownloadOffPeakLimit  string
	DeliveryLocalUploadOffPeakLimit    string
	lastoreDaemonStatus                LastoreDaemonStatus
	UpdateStatus                       string
	PlatformUpdate                     bool

	PlatformUrl            string // 更新接口地址
	StartCheckRange        []int  // 开机检查更新区间
	GetHardwareIdByHelper  bool   // machineID是否直接从sync helper获取
	IncludeDiskInfo        bool   // machineID是否包含硬盘信息
	PostUpgradeCron        string // 更新上报间隔
	UpdateTime             string // 定时更新
	PlatformDisabled       DisabledStatus
	EnableVersionCheck     bool
	UpdateProcessUpload    bool
	PlatformRepoComponents string // 更新平台仓库组件
	UpgradeDeliveryEnabled bool   // 传递优化服务是否开机可用

	ClassifiedUpdatablePackages map[string][]string
	OnlineCache                 string

	EnableCoreList    bool
	ClientPackageName string

	SystemCustomSource      []string      // 系统更新自定义仓库内容
	SecurityCustomSource    []string      // 安全更新自定义仓库内容
	SystemOemSourceConfig   OemRepoConfig // 系统更新OEM仓库配置 来源/etc/deepin/lastore-daemon/oem-repo.conf.d
	SecurityOemSourceConfig OemRepoConfig // 安全更新OEM仓库配置 来源/etc/deepin/lastore-daemon/oem-repo.conf.d
	SystemRepoType          RepoType      // 系统更新仓库类型
	SecurityRepoType        RepoType      // 安全更新仓库类型

	filePath string
	statusMu sync.RWMutex

	dsettingsChangedCbMap   map[string]func(interface{}, interface{})
	dsettingsChangedCbMapMu sync.Mutex
}

func NewConfig(configPath string) *Config {
	dc := getConfigFromDSettings()
	dc.filePath = configPath
	if !dc.useDSettings { // 从config文件迁移至DSettings
		var c *Config = &Config{
			UpdateMode: system.SystemUpdate | system.SecurityUpdate,
		}
		err := system.DecodeJson(configPath, &c)
		if err != nil {
			logger.Debugf("Can't load config file: %v\n", err)
		} else {
			logger.Info("transfer config.json to DSettings")
			dc.json2DSettings(c)
		}
		_ = dc.SetUseDSettings(true)
	}
	if dc.CheckInterval < MinCheckInterval {
		_ = dc.SetCheckInterval(MinCheckInterval)
	}
	if dc.Version == "" {
		_ = dc.SetVersion(ConfigVersion)
		_ = dc.SetCheckInterval(time.Hour * 24 * 7)
		_ = dc.SetCleanInterval(time.Hour * 24 * 7)
	}

	return dc
}

const (
	dSettingsAppID                                   = "org.deepin.dde.lastore"
	dSettingsLastoreName                             = "org.deepin.dde.lastore"
	dSettingsKeyUseDSettings                         = "use-dsettings"
	dSettingsKeyVersion                              = "version"
	dSettingsKeyAutoCheckUpdates                     = "auto-check-updates"
	dSettingsKeyDisableUpdateMetadata                = "disable-update-metadata"
	DSettingsKeyAutoDownloadUpdates                  = "auto-download-updates"
	dSettingsKeyAutoClean                            = "auto-clean"
	dSettingsKeyMirrorSource                         = "mirror-source"
	dSettingsKeyUpdateNotify                         = "update-notify"
	DSettingsKeyCheckInterval                        = "check-interval"
	dSettingsKeyCleanInterval                        = "clean-interval"
	dSettingsKeyUpdateMode                           = "update-mode"
	dSettingsKeyCheckUpdateMode                      = "check-update-mode"
	dSettingsKeyCleanIntervalCacheOverLimit          = "clean-internal-cache-over-limit"
	dSettingsKeyAppstoreRegion                       = "appstore-region"
	dSettingsKeyLastCheckTime                        = "last-check-time"
	dSettingsKeyLastCleanTime                        = "last-clean-time"
	dSettingsKeyLastCheckCacheSizeTime               = "last-check-cache-size-time"
	dSettingsKeyRepository                           = "repository"
	dSettingsKeyMirrorsUrl                           = "mirrors-url"
	dSettingsKeyAllowInstallRemovePkgExecPaths       = "allow-install-remove-pkg-exec-paths"
	dSettingsKeyAutoInstallUpdates                   = "auto-install-updates"
	dSettingsKeyAutoInstallUpdateType                = "auto-install-update-type"
	dSettingsKeyAllowPostSystemUpgradeMessageVersion = "allow-post-system-upgrade-message-version"
	dSettingsKeyUpgradeStatus                        = "upgrade-status"
	dSettingsKeyIdleDownloadConfig                   = "idle-download-config"
	dSettingsKeySystemSourceList                     = "system-sources"
	dSettingsKeyNonUnknownList                       = "non-unknown-sources"
	DSettingsKeyDownloadSpeedLimit                   = "download-speed-limit"
	dSettingsKeyLocalDownloadSpeedLimit              = "local-download-speed-limit"
	DSettingsKeyLastoreDaemonStatus                  = "lastore-daemon-status"
	dSettingsKeyUpdateStatus                         = "update-status"
	DSettingsKeyPlatformUpdate                       = "platform-update"
	DSettingsKeyPlatformUrl                          = "platform-url"
	DSettingsKeyStartCheckRange                      = "start-check-range"
	DSettingsKeyIncludeDiskInfo                      = "include-disk-info"
	dSettingsKeyPostUpgradeOnCalendar                = "post-upgrade-on-calendar"
	dSettingsKeyUpdateTime                           = "update-time"
	dSettingsKeyPlatformDisabled                     = "platform-disabled"
	dSettingsKeyEnableVersionCheck                   = "enable-version-check"
	dSettingsKeyUpdateProcessUpload                  = "update-process-upload"
	dSettingsKeyEnableCoreList                       = "enable-core-list"
	dSettingsKeyClientPackageName                    = "client-package-name"
	DSettingsKeyUpgradeDeliveryEnabled               = "upgrade-delivery-enabled"
	dSettingsKeySystemCustomSource                   = "system-custom-source"
	dSettingsKeySecurityCustomSource                 = "security-custom-source"
	dSettingsKeySystemRepoType                       = "system-repo-type"
	dSettingsKeySecurityRepoType                     = "security-repo-type"
	dSettingsKeyPlatformRepoComponents               = "platform-repo-components"
	DSettingsKeyIncrementalUpdate                    = "incremental-update"
	DSettingsKeyIntranetUpdate                       = "intranet-update"
	DSettingsKeyGetHardwareIdByHelper                = "hardware-id-from-helper"
	DSettingsKeyDeliveryRemoteDownloadGlobalLimit    = "delivery-remote-download-global-limit"
	DSettingsKeyDeliveryRemoteUploadGlobalLimit      = "delivery-remote-upload-global-limit"
	DSettingsKeyDeliveryRemoteDownloadPeakLimit      = "delivery-remote-download-peak-limit"
	DSettingsKeyDeliveryRemoteUploadPeakLimit        = "delivery-remote-upload-peak-limit"
	DSettingsKeyDeliveryRemoteDownloadOffPeakLimit   = "delivery-remote-download-offpeak-limit"
	DSettingsKeyDeliveryRemoteUploadOffPeakLimit     = "delivery-remote-upload-offpeak-limit"
	dSettingsKeyDeliveryLocalDownloadGlobalLimit     = "delivery-local-download-global-limit"
	dSettingsKeyDeliveryLocalUploadGlobalLimit       = "delivery-local-upload-global-limit"
	dSettingsKeyDeliveryLocalDownloadPeakLimit       = "delivery-local-download-peak-limit"
	dSettingsKeyDeliveryLocalUploadPeakLimit         = "delivery-local-upload-peak-limit"
	dSettingsKeyDeliveryLocalDownloadOffPeakLimit    = "delivery-local-download-offpeak-limit"
	dSettingsKeyDeliveryLocalUploadOffPeakLimit      = "delivery-local-upload-offpeak-limit"
)

const configTimeLayout = "2006-01-02T15:04:05.999999999-07:00"

var (
	legacyOnlineCachePath     = "/tmp/platform_cache.json"
	legacyClassifiedCachePath = "/tmp/classified_cache.json"
	onlineCachePath           = "/var/lib/lastore/platform_cache.json"
	classifiedCachePath       = "/var/lib/lastore/classified_cache.json"
)

func getConfigFromDSettings() *Config {
	c := &Config{}
	sysBus, err := dbus.SystemBus()
	if err != nil {
		return c
	}
	ds := ConfigManager.NewConfigManager(sysBus)
	dsPath, err := ds.AcquireManager(0, dSettingsAppID, dSettingsLastoreName, "")
	if err != nil {
		logger.Warning(err)
		return c
	}
	c.dsLastoreManager, err = ConfigManager.NewManager(sysBus, dsPath)
	if err != nil {
		logger.Warning(err)
		return c
	}
	systemSigLoop := dbusutil.NewSignalLoop(sysBus, 10)
	systemSigLoop.Start()
	c.dsLastoreManager.InitSignalExt(systemSigLoop, true)
	// 从DSettings获取所有内容，更新config
	v, err := c.dsLastoreManager.Value(0, dSettingsKeyUseDSettings)
	if err != nil {
		logger.Warning(err)
	} else {
		c.useDSettings = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyVersion)
	if err != nil {
		logger.Warning(err)
	} else {
		c.Version = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAutoCheckUpdates)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AutoCheckUpdates = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDisableUpdateMetadata)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DisableUpdateMetadata = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyAutoDownloadUpdates)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AutoDownloadUpdates = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAutoClean)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AutoClean = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyIncrementalUpdate)
	if err != nil {
		logger.Warning(err)
	} else {
		c.IncrementalUpdate = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyIntranetUpdate)
	if err != nil {
		logger.Warning(err)
	} else {
		c.IntranetUpdate = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyMirrorSource)
	if err != nil {
		logger.Warning(err)
	} else {
		c.MirrorSource = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpdateNotify)
	if err != nil {
		logger.Warning(err)
	} else {
		c.UpdateNotify = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyCheckInterval)
	if err != nil {
		logger.Warning(err)
	} else {
		c.CheckInterval = time.Duration(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyCleanInterval)
	if err != nil {
		logger.Warning(err)
	} else {
		c.CleanInterval = time.Duration(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpdateMode)
	if err != nil {
		logger.Warning(err)
	} else {
		if (c.UpdateMode & system.OnlySecurityUpdate) != 0 {
			c.UpdateMode &= ^system.OnlySecurityUpdate
			c.UpdateMode |= system.SecurityUpdate
		}
		c.UpdateMode = system.UpdateType(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyCleanIntervalCacheOverLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.CleanIntervalCacheOverLimit = time.Duration(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAppstoreRegion)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AppstoreRegion = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyLastCheckTime)
	if err != nil {
		logger.Warning(err)
	} else {
		s := v.Value().(string)
		c.LastCheckTime, err = time.Parse(configTimeLayout, s)
		if err != nil {
			logger.Warning(err)
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyLastCleanTime)
	if err != nil {
		logger.Warning(err)
	} else {
		s := v.Value().(string)
		c.LastCleanTime, err = time.Parse(configTimeLayout, s)
		if err != nil {
			logger.Warning(err)
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyLastCheckCacheSizeTime)
	if err != nil {
		logger.Warning(err)
	} else {
		s := v.Value().(string)
		c.LastCheckCacheSizeTime, err = time.Parse(configTimeLayout, s)
		if err != nil {
			logger.Warning(err)
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyRepository)
	if err != nil {
		logger.Warning(err)
	} else {
		c.Repository = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyMirrorsUrl)
	if err != nil {
		logger.Warning(err)
	} else {
		c.MirrorsUrl = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAllowInstallRemovePkgExecPaths)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.AllowInstallRemovePkgExecPaths = append(c.AllowInstallRemovePkgExecPaths, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAutoInstallUpdates)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AutoInstallUpdates = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAutoInstallUpdateType)
	if err != nil {
		logger.Warning(err)
	} else {
		c.AutoInstallUpdateType = system.UpdateType(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyAllowPostSystemUpgradeMessageVersion)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.AllowPostSystemUpgradeMessageVersion = append(c.AllowPostSystemUpgradeMessageVersion, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpgradeStatus)
	if err != nil {
		logger.Warning(err)
	} else {
		statusContent := v.Value().(string)
		err = json.Unmarshal([]byte(statusContent), &c.UpgradeStatus)
		if err != nil {
			logger.Warning(err)
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyIdleDownloadConfig)
	if err != nil {
		logger.Warning(err)
	} else {
		c.IdleDownloadConfig = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeySystemSourceList)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.SystemSourceList = append(c.SystemSourceList, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyNonUnknownList)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.NonUnknownList = append(c.NonUnknownList, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDownloadSpeedLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DownloadSpeedLimitConfig = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyLocalDownloadSpeedLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.LocalDownloadSpeedLimitConfig = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteDownloadGlobalLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteDownloadGlobalLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteUploadGlobalLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteUploadGlobalLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteDownloadPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteDownloadPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteUploadPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteUploadPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteDownloadOffPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteDownloadOffPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyDeliveryRemoteUploadOffPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryRemoteUploadOffPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadGlobalLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalDownloadGlobalLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadGlobalLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalUploadGlobalLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalDownloadPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalUploadPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadOffPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalDownloadOffPeakLimit = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadOffPeakLimit)
	if err != nil {
		logger.Warning(err)
	} else {
		c.DeliveryLocalUploadOffPeakLimit = v.Value().(string)
	}

	updateLastoreDaemonStatus := func() {
		v, err = c.dsLastoreManager.Value(0, DSettingsKeyLastoreDaemonStatus)
		if err != nil {
			logger.Warning(err)
		} else {
			c.lastoreDaemonStatus = LastoreDaemonStatus(v.Value().(int64))
		}
	}
	updateLastoreDaemonStatus()

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyCheckUpdateMode)
	if err != nil {
		logger.Warning(err)
	} else {
		c.CheckUpdateMode = system.UpdateType(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpdateStatus)
	if err != nil {
		logger.Warning(err)
	} else {
		c.UpdateStatus = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyPlatformUpdate)
	if err != nil {
		logger.Warning(err)
	} else {
		c.PlatformUpdate = v.Value().(bool)
	}

	var url string
	v, err = c.dsLastoreManager.Value(0, DSettingsKeyPlatformUrl)
	if err != nil {
		logger.Warning(err)
	} else {
		url = v.Value().(string)
	}
	c.PlatformUrl = url

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyPlatformRepoComponents)
	if err != nil {
		logger.Warning(err)
	} else {
		c.PlatformRepoComponents = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyPostUpgradeOnCalendar)
	if err != nil {
		logger.Warning(err)
	} else {
		c.PostUpgradeCron = v.Value().(string)
	}

	var checkRange []int64
	v, err = c.dsLastoreManager.Value(0, DSettingsKeyStartCheckRange)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			checkRange = append(checkRange, s.Value().(int64))
		}
	}

	if len(checkRange) != 2 {
		c.StartCheckRange = []int{1800, 21600}
	} else {
		if checkRange[0] < checkRange[1] {
			c.StartCheckRange = []int{int(checkRange[0]), int(checkRange[1])}
		} else {
			c.StartCheckRange = []int{int(checkRange[1]), int(checkRange[0])}
		}
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyIncludeDiskInfo)
	if err != nil {
		logger.Warning(err)
		c.IncludeDiskInfo = true
	} else {
		c.IncludeDiskInfo = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpdateTime)
	if err != nil {
		logger.Warning(err)
	} else {
		c.UpdateTime = v.Value().(string)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyPlatformDisabled)
	if err != nil {
		logger.Warning(err)
	} else {
		c.PlatformDisabled = DisabledStatus(v.Value().(int64))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyEnableVersionCheck)
	if err != nil {
		logger.Warning(err)
	} else {
		c.EnableVersionCheck = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyUpdateProcessUpload)
	if err != nil {
		logger.Warning(err)
	} else {
		c.UpdateProcessUpload = v.Value().(bool)
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeyEnableCoreList)
	if err != nil {
		logger.Warning(err)
	} else {
		c.EnableCoreList = v.Value().(bool)
	}
	v, err = c.dsLastoreManager.Value(0, dSettingsKeyClientPackageName)
	if err != nil {
		logger.Warning(err)
	} else {
		c.ClientPackageName = v.Value().(string)
	}

	updateUpgradeDeliveryEnabled := func() {
		v, err = c.dsLastoreManager.Value(0, DSettingsKeyUpgradeDeliveryEnabled)
		if err != nil {
			logger.Warning(err)
			c.UpgradeDeliveryEnabled = false
		} else {
			c.UpgradeDeliveryEnabled = v.Value().(bool)
		}
	}
	updateUpgradeDeliveryEnabled()

	v, err = c.dsLastoreManager.Value(0, dSettingsKeySystemCustomSource)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.SystemCustomSource = append(c.SystemCustomSource, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeySecurityCustomSource)
	if err != nil {
		logger.Warning(err)
	} else {
		for _, s := range v.Value().([]dbus.Variant) {
			c.SecurityCustomSource = append(c.SecurityCustomSource, s.Value().(string))
		}
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeySystemRepoType)
	if err != nil {
		logger.Warning(err)
	} else {
		c.SystemRepoType = RepoType(v.Value().(string))
	}

	v, err = c.dsLastoreManager.Value(0, dSettingsKeySecurityRepoType)
	if err != nil {
		logger.Warning(err)
	} else {
		c.SecurityRepoType = RepoType(v.Value().(string))
	}

	v, err = c.dsLastoreManager.Value(0, DSettingsKeyGetHardwareIdByHelper)
	if err != nil {
		logger.Warning(err)
	} else {
		c.GetHardwareIdByHelper = v.Value().(bool)
	}

	err = c.recoveryAndApplyOemFlag(system.SystemUpdate)
	if err != nil {
		logger.Warning(err)
	}

	err = c.recoveryAndApplyOemFlag(system.SecurityUpdate)
	if err != nil {
		logger.Warning(err)
	}

	// classifiedCachePath和onlineCachePath两项数据没有存储在dconfig中，是因为数据量太大，dconfig不支持存储这么长的数据
	content, err := readCacheWithLegacyFallback(classifiedCachePath, legacyClassifiedCachePath)
	if err != nil {
		if !os.IsNotExist(err) {
			logger.Warning(err)
		}
	} else {
		c.ClassifiedUpdatablePackages = make(map[string][]string)
		err = json.Unmarshal(content, &c.ClassifiedUpdatablePackages)
		if err != nil {
			logger.Warning(err)
		}
	}

	content, err = readCacheWithLegacyFallback(onlineCachePath, legacyOnlineCachePath)
	if err != nil {
		if !os.IsNotExist(err) {
			logger.Warning(err)
		}
	} else {
		c.OnlineCache = string(content)
	}
	c.OtherSourceList = append(c.OtherSourceList, "/etc/apt/sources.list.d/driver.list")
	c.SecuritySourceList = append(c.SecuritySourceList, system.SecuritySourceFile)

	_, err = c.dsLastoreManager.ConnectValueChanged(func(key string) {
		logger.Infof("config update: key=%s", key)
		switch key {
		case DSettingsKeyIntranetUpdate:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyIntranetUpdate)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.PlatformUpdate
				newValue := v.Value().(bool)
				c.IntranetUpdate = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyPlatformUpdate:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyPlatformUpdate)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.PlatformUpdate
				newValue := v.Value().(bool)
				c.PlatformUpdate = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyPlatformUrl:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyPlatformUrl)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.PlatformUrl
				newValue := v.Value().(string)
				c.PlatformUrl = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyGetHardwareIdByHelper:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyGetHardwareIdByHelper)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.GetHardwareIdByHelper
				newValue := v.Value().(bool)
				c.GetHardwareIdByHelper = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyIncludeDiskInfo:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyIncludeDiskInfo)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.IncludeDiskInfo
				newValue := v.Value().(bool)
				c.IncludeDiskInfo = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyIncrementalUpdate:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyIncrementalUpdate)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.IncrementalUpdate
				newValue := v.Value().(bool)
				c.IncrementalUpdate = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyAutoDownloadUpdates:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyAutoDownloadUpdates)
			if err != nil {
				logger.Warning(err)
			} else {
				oldValue := c.AutoDownloadUpdates
				newValue := v.Value().(bool)
				c.AutoDownloadUpdates = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyUpgradeDeliveryEnabled:
			v, err = c.dsLastoreManager.Value(0, DSettingsKeyUpgradeDeliveryEnabled)
			if err != nil {
				logger.Warningf("failed to get value for %s: %v", DSettingsKeyUpgradeDeliveryEnabled, err)
			} else {
				oldValue := c.UpgradeDeliveryEnabled
				newValue := v.Value().(bool)
				c.UpgradeDeliveryEnabled = newValue
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldValue, newValue)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		case DSettingsKeyLastoreDaemonStatus:
			oldStatus := c.lastoreDaemonStatus
			updateLastoreDaemonStatus()
			newStatus := c.lastoreDaemonStatus
			if (oldStatus & DisableUpdate) != (newStatus & DisableUpdate) {
				c.dsettingsChangedCbMapMu.Lock()
				cb := c.dsettingsChangedCbMap[key]
				if cb != nil {
					go cb(oldStatus, newStatus)
				}
				c.dsettingsChangedCbMapMu.Unlock()
			}
		}
	})
	if err != nil {
		logger.Warning(err)
	}
	return c
}

func (c *Config) json2DSettings(oldConfig *Config) {
	_ = c.UpdateLastCheckTime()
	_ = c.UpdateLastCleanTime()
	_ = c.UpdateLastCheckCacheSizeTime()
	_ = c.SetVersion(oldConfig.Version)
	_ = c.SetAutoCheckUpdates(oldConfig.AutoCheckUpdates)
	_ = c.SetDisableUpdateMetadata(oldConfig.DisableUpdateMetadata)
	_ = c.SetUpdateNotify(oldConfig.UpdateNotify)
	_ = c.SetAutoDownloadUpdates(oldConfig.AutoDownloadUpdates)
	_ = c.SetAutoClean(oldConfig.AutoClean)
	_ = c.SetMirrorSource(oldConfig.MirrorSource)
	_ = c.SetAppstoreRegion(oldConfig.AppstoreRegion)
	_ = c.SetUpdateMode(oldConfig.UpdateMode)
	_ = c.SetCleanIntervalCacheOverLimit(oldConfig.CleanIntervalCacheOverLimit)
	_ = c.SetAutoInstallUpdates(oldConfig.AutoInstallUpdates)
	_ = c.SetAutoInstallUpdateType(oldConfig.AutoInstallUpdateType)
	_ = c.SetAllowPostSystemUpgradeMessageVersion(append(oldConfig.AllowPostSystemUpgradeMessageVersion, c.AllowPostSystemUpgradeMessageVersion...))
	_ = c.SetCheckInterval(oldConfig.CheckInterval)
	_ = c.SetCleanInterval(oldConfig.CleanInterval)
	_ = c.SetRepository(oldConfig.Repository)
	_ = c.SetMirrorsUrl(oldConfig.MirrorsUrl)
	_ = c.SetAllowInstallRemovePkgExecPaths(append(oldConfig.AllowInstallRemovePkgExecPaths, c.AllowInstallRemovePkgExecPaths...))
}

func (c *Config) ConnectConfigChanged(key string, cb func(interface{}, interface{})) {
	if c.dsettingsChangedCbMap == nil {
		c.dsettingsChangedCbMap = make(map[string]func(interface{}, interface{}))
	}
	c.dsettingsChangedCbMapMu.Lock()
	c.dsettingsChangedCbMap[key] = cb
	c.dsettingsChangedCbMapMu.Unlock()
}

func (c *Config) UpdateLastCheckTime() error {
	c.LastCheckTime = time.Now()
	return c.save(dSettingsKeyLastCheckTime, c.LastCheckTime.Format(configTimeLayout))
}

func (c *Config) UpdateLastCleanTime() error {
	c.LastCleanTime = time.Now()
	return c.save(dSettingsKeyLastCleanTime, c.LastCleanTime.Format(configTimeLayout))
}

func (c *Config) UpdateLastCheckCacheSizeTime() error {
	c.LastCheckCacheSizeTime = time.Now()
	return c.save(dSettingsKeyLastCheckCacheSizeTime, c.LastCheckCacheSizeTime.Format(configTimeLayout))
}

func (c *Config) SetVersion(version string) error {
	c.Version = version
	return c.save(dSettingsKeyVersion, version)
}

func (c *Config) SetAutoCheckUpdates(enable bool) error {
	c.AutoCheckUpdates = enable
	return c.save(dSettingsKeyAutoCheckUpdates, enable)
}

func (c *Config) SetDisableUpdateMetadata(disable bool) error {
	c.DisableUpdateMetadata = disable
	return c.save(dSettingsKeyDisableUpdateMetadata, disable)
}

func (c *Config) SetUpdateNotify(enable bool) error {
	c.UpdateNotify = enable
	return c.save(dSettingsKeyUpdateNotify, enable)
}

func (c *Config) SetAutoDownloadUpdates(enable bool) error {
	c.AutoDownloadUpdates = enable
	return c.save(DSettingsKeyAutoDownloadUpdates, enable)
}

func (c *Config) SetAutoClean(enable bool) error {
	c.AutoClean = enable
	return c.save(dSettingsKeyAutoClean, enable)
}

func (c *Config) SetIncrementalUpdate(enable bool) error {
	c.IncrementalUpdate = enable
	return c.save(DSettingsKeyIncrementalUpdate, enable)
}

func (c *Config) UseIncrementalUpdate() bool {
	return !c.IntranetUpdate && !c.UpgradeDeliveryEnabled && c.IncrementalUpdate
}

func (c *Config) SetMirrorSource(id string) error {
	c.MirrorSource = id
	return c.save(dSettingsKeyMirrorSource, id)
}

func (c *Config) SetAppstoreRegion(region string) error {
	c.AppstoreRegion = region
	return c.save(dSettingsKeyAppstoreRegion, region)
}

func (c *Config) SetUpdateMode(mode system.UpdateType) error {
	c.UpdateMode = mode
	return c.save(dSettingsKeyUpdateMode, mode)
}

func (c *Config) SetCheckUpdateMode(mode system.UpdateType) error {
	c.CheckUpdateMode = mode
	return c.save(dSettingsKeyCheckUpdateMode, mode)
}

func (c *Config) SetCleanIntervalCacheOverLimit(duration time.Duration) error {
	c.CleanIntervalCacheOverLimit = duration
	return c.save(dSettingsKeyCleanIntervalCacheOverLimit, duration)
}

func (c *Config) SetAutoInstallUpdates(autoInstall bool) error {
	c.AutoInstallUpdates = autoInstall
	return c.save(dSettingsKeyAutoInstallUpdates, autoInstall)
}

func (c *Config) SetAutoInstallUpdateType(updateType system.UpdateType) error {
	c.AutoInstallUpdateType = updateType
	return c.save(dSettingsKeyAutoInstallUpdateType, updateType)
}

func (c *Config) SetAllowPostSystemUpgradeMessageVersion(version []string) error {
	c.AllowPostSystemUpgradeMessageVersion = version
	return c.save(dSettingsKeyAllowPostSystemUpgradeMessageVersion, version)
}

func (c *Config) SetUpgradeStatusAndReason(status system.UpgradeStatusAndReason) error {
	logger.Infof("Update UpgradeStatusAndReason to %+v", status)
	c.UpgradeStatus = status
	v, err := json.Marshal(status)
	if err != nil {
		logger.Warning(err)
	}
	return c.save(dSettingsKeyUpgradeStatus, string(v))
}

func (c *Config) SetUseDSettings(use bool) error {
	c.useDSettings = use
	return c.save(dSettingsKeyUseDSettings, use)
}

func (c *Config) SetIdleDownloadConfig(idleConfig string) error {
	c.IdleDownloadConfig = idleConfig
	return c.save(dSettingsKeyIdleDownloadConfig, idleConfig)
}

func (c *Config) SetCheckInterval(interval time.Duration) error {
	c.CheckInterval = interval
	return c.save(DSettingsKeyCheckInterval, interval)
}

func (c *Config) SetCleanInterval(interval time.Duration) error {
	c.CleanInterval = interval
	return c.save(dSettingsKeyCleanInterval, interval)
}

func (c *Config) SetRepository(repository string) error {
	c.Repository = repository
	return c.save(dSettingsKeyRepository, repository)
}

func (c *Config) SetMirrorsUrl(mirrorsUrl string) error {
	c.MirrorsUrl = mirrorsUrl
	return c.save(dSettingsKeyMirrorsUrl, mirrorsUrl)
}

func (c *Config) SetAllowInstallRemovePkgExecPaths(paths []string) error {
	c.AllowInstallRemovePkgExecPaths = paths
	return c.save(dSettingsKeyAllowInstallRemovePkgExecPaths, paths)
}

// func (c *Config) SetNeedDownloadSize(size float64) error {
//	c.needDownloadSize = size
//	return c.save(dSettingsKeyNeedDownloadSize, size)
// }

func (c *Config) SetLastCheckTime(lastCheckTime time.Time) error {
	c.LastCheckTime = lastCheckTime
	return c.save(dSettingsKeyLastCheckTime, c.LastCheckTime.Format(configTimeLayout))
}

func (c *Config) SetDownloadSpeedLimitConfig(config string) error {
	c.DownloadSpeedLimitConfig = config
	return c.save(DSettingsKeyDownloadSpeedLimit, config)
}

func (c *Config) SetLocalDownloadSpeedLimitConfig(config string) error {
	c.LocalDownloadSpeedLimitConfig = config
	return c.save(dSettingsKeyLocalDownloadSpeedLimit, config)
}

func (c *Config) SetDeliveryRemoteDownloadGlobalLimit(config string) error {
	c.DeliveryRemoteDownloadGlobalLimit = config
	return c.save(DSettingsKeyDeliveryRemoteDownloadGlobalLimit, config)
}

func (c *Config) SetDeliveryRemoteUploadGlobalLimit(config string) error {
	c.DeliveryRemoteUploadGlobalLimit = config
	return c.save(DSettingsKeyDeliveryRemoteUploadGlobalLimit, config)
}

func (c *Config) SetDeliveryRemoteDownloadPeakLimit(config string) error {
	c.DeliveryRemoteDownloadPeakLimit = config
	return c.save(DSettingsKeyDeliveryRemoteDownloadPeakLimit, config)
}

func (c *Config) SetDeliveryRemoteUploadPeakLimit(config string) error {
	c.DeliveryRemoteUploadPeakLimit = config
	return c.save(DSettingsKeyDeliveryRemoteUploadPeakLimit, config)
}

func (c *Config) SetDeliveryRemoteDownloadOffPeakLimit(config string) error {
	c.DeliveryRemoteDownloadOffPeakLimit = config
	return c.save(DSettingsKeyDeliveryRemoteDownloadOffPeakLimit, config)
}

func (c *Config) SetDeliveryRemoteUploadOffPeakLimit(config string) error {
	c.DeliveryRemoteUploadOffPeakLimit = config
	return c.save(DSettingsKeyDeliveryRemoteUploadOffPeakLimit, config)
}

func (c *Config) SetDeliveryLocalDownloadGlobalLimit(config string) error {
	c.DeliveryLocalDownloadGlobalLimit = config
	return c.save(dSettingsKeyDeliveryLocalDownloadGlobalLimit, config)
}

func (c *Config) SetDeliveryLocalUploadGlobalLimit(config string) error {
	c.DeliveryLocalUploadGlobalLimit = config
	return c.save(dSettingsKeyDeliveryLocalUploadGlobalLimit, config)
}

func (c *Config) SetDeliveryLocalDownloadPeakLimit(config string) error {
	c.DeliveryLocalDownloadPeakLimit = config
	return c.save(dSettingsKeyDeliveryLocalDownloadPeakLimit, config)
}

func (c *Config) SetDeliveryLocalUploadPeakLimit(config string) error {
	c.DeliveryLocalUploadPeakLimit = config
	return c.save(dSettingsKeyDeliveryLocalUploadPeakLimit, config)
}

func (c *Config) SetDeliveryLocalDownloadOffPeakLimit(config string) error {
	c.DeliveryLocalDownloadOffPeakLimit = config
	return c.save(dSettingsKeyDeliveryLocalDownloadOffPeakLimit, config)
}

func (c *Config) SetDeliveryLocalUploadOffPeakLimit(config string) error {
	c.DeliveryLocalUploadOffPeakLimit = config
	return c.save(dSettingsKeyDeliveryLocalUploadOffPeakLimit, config)
}

func (c *Config) SetLastoreDaemonStatus(status LastoreDaemonStatus) error {
	c.statusMu.Lock()
	c.lastoreDaemonStatus = status
	c.statusMu.Unlock()
	return c.save(DSettingsKeyLastoreDaemonStatus, status)
}

// UpdateLastoreDaemonStatus isSet: true 该位置1; false 该位清零
func (c *Config) UpdateLastoreDaemonStatus(status LastoreDaemonStatus, isSet bool) error {
	c.statusMu.Lock()
	if isSet {
		c.lastoreDaemonStatus |= status
	} else {
		c.lastoreDaemonStatus &= ^status
	}
	c.statusMu.Unlock()
	return c.save(DSettingsKeyLastoreDaemonStatus, c.lastoreDaemonStatus)
}

func (c *Config) GetLastoreDaemonStatus() LastoreDaemonStatus {
	c.statusMu.RLock()
	defer c.statusMu.RUnlock()
	return c.lastoreDaemonStatus
}

func (c *Config) GetLastoreDaemonStatusByBit(key LastoreDaemonStatus) LastoreDaemonStatus {
	c.statusMu.RLock()
	defer c.statusMu.RUnlock()
	return c.lastoreDaemonStatus & key
}

func (c *Config) SetUpdateStatus(status string) error {
	c.UpdateStatus = status
	return c.save(dSettingsKeyUpdateStatus, status)
}

func (c *Config) SetInstallUpdateTime(delayed string) error {
	c.UpdateTime = delayed
	return c.save(dSettingsKeyUpdateTime, c.UpdateTime)
}

func (c *Config) SetSystemCustomSource(sources []string) error {
	c.SystemCustomSource = sources
	return c.save(dSettingsKeySystemCustomSource, sources)
}

func (c *Config) SetSecurityCustomSource(sources []string) error {
	c.SecurityCustomSource = sources
	return c.save(dSettingsKeySecurityCustomSource, sources)
}

func (c *Config) SetSystemRepoType(typ RepoType) error {
	c.SystemRepoType = typ
	return c.save(dSettingsKeySystemRepoType, typ)
}

func (c *Config) SetUpgradeDeliveryEnabled(enable bool) error {
	c.UpgradeDeliveryEnabled = enable
	return c.save(DSettingsKeyUpgradeDeliveryEnabled, enable)
}

func (c *Config) SetSecurityRepoType(typ RepoType) error {
	c.SecurityRepoType = typ
	return c.save(dSettingsKeySecurityRepoType, typ)
}

func (c *Config) SetStartCheckRange(checkRange []int) error {
	c.StartCheckRange = checkRange

	// TODO: remove this after bug of dde-dconfig fixed
	variants := make([]dbus.Variant, 0, len(checkRange))
	for _, item := range checkRange {
		variants = append(variants, dbus.MakeVariant(int64(item)))
	}

	return c.save(DSettingsKeyStartCheckRange, variants)
}

func (c *Config) SetClassifiedUpdatablePackages(pkgMap map[string][]string) error {
	content, err := json.Marshal(pkgMap)
	if err != nil {
		logger.Warning(err)
		return err
	}
	c.ClassifiedUpdatablePackages = pkgMap
	return utils.WriteFileSecurely(classifiedCachePath, content, 0644)
}

func (c *Config) SetOnlineCache(cache string) error {
	c.OnlineCache = cache
	return utils.WriteFileSecurely(onlineCachePath, []byte(cache), 0644)
}

func readCacheWithLegacyFallback(path, legacyPath string) ([]byte, error) {
	content, err := os.ReadFile(path)
	if err == nil || !errors.Is(err, os.ErrNotExist) {
		return content, err
	}
	if legacyPath == "" {
		return nil, err
	}
	return os.ReadFile(legacyPath)
}

func (c *Config) GetPlatformStatusDisable(status DisabledStatus) bool {
	return c.PlatformDisabled&status == status
}

func (c *Config) save(key string, v interface{}) error {
	if c.dsLastoreManager != nil {
		return c.dsLastoreManager.SetValue(0, key, dbus.MakeVariant(v))
	}
	logger.Info("not exist lastore dsettings")
	return system.EncodeJson(c.filePath, c)
}

func (c *Config) ResetDSettings(key string) error {
	if c.dsLastoreManager != nil {
		return c.dsLastoreManager.Reset(0, key)
	}
	return nil
}
