using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JJServiceManager
{
/// 바인딩용 기본 클래스
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool Set(ref T field, T value, [CallerMemberName] string name = null)
{
if (EqualityComparer.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(name);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
/// 로그창 띄우기 방식
public enum LogWindowMode
{
Individual = 0, // 개별 창
Tabs = 1, // 하나의 창에 탭
Split = 2 // 창을 좌우로 나누어 비교
}
/// Esc 키 동작
public enum EscAction
{
Tray = 0, // 트레이로 (백그라운드)
Exit = 1 // 완전 종료
}
/// 등록된 서비스 한 건
public class ServiceEntry
{
public string ServiceName { get; set; } = "";
public string DisplayName { get; set; } = "";
/// 로그 파일 경로 또는 로그 폴더 경로 (없으면 빈 값)
public string LogPath { get; set; } = "";
/// true면 LogPath는 폴더이며, 그 안의 가장 최근 수정 파일을 표시
public bool LogIsFolder { get; set; }
/// 로그 인코딩: auto / utf-8 / cp949
public string LogEncoding { get; set; } = "auto";
}
/// 프로그램 설정 (settings.json)
public class AppSettings
{
public List Services { get; set; } = new List();
/// 컴퓨터 시작 시 기동
public bool RunAtStartup { get; set; }
/// 단축키 사용 여부
public bool HotkeyEnabled { get; set; } = true;
/// 단축키 보조키 (System.Windows.Input.ModifierKeys 값)
public int HotkeyModifiers { get; set; } = 2 | 4; // Ctrl + Shift
/// 단축키 키 (System.Windows.Input.Key 값)
public int HotkeyKey { get; set; } = 44; // Key.A
/// 서비스 시작 시 로그보기 = 작업 로그를 화면 하단에 표시할지 여부
public bool ShowOperationLog { get; set; } = true;
/// 로그창 띄우기 방식
public LogWindowMode LogWindowMode { get; set; } = LogWindowMode.Individual;
/// Esc 키 동작
public EscAction EscAction { get; set; } = EscAction.Tray;
/// Windows 강제종료 / 재시작 버튼 표시
public bool ShowShutdownButtons { get; set; } = true;
/// 창 크기·위치
public double WindowLeft { get; set; } = double.NaN;
public double WindowTop { get; set; } = double.NaN;
public double WindowWidth { get; set; } = 1000;
public double WindowHeight { get; set; } = 720;
}
/// 설정 파일 저장/불러오기
public static class SettingsStore
{
public static string DataFolder { get; } =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "JJServiceManager");
public static string SettingsPath => Path.Combine(DataFolder, "settings.json");
private static readonly JsonSerializerOptions Options = new JsonSerializerOptions
{
WriteIndented = true,
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
Converters = { new JsonStringEnumConverter() }
};
public static AppSettings Load()
{
try
{
if (File.Exists(SettingsPath))
{
var json = File.ReadAllText(SettingsPath);
var s = JsonSerializer.Deserialize(json, Options);
if (s != null)
{
s.Services ??= new List();
return s;
}
}
}
catch
{
// 설정 파일이 손상된 경우 기본값 사용 (원본 파일은 지우지 않음)
}
return new AppSettings();
}
public static void Save(AppSettings settings)
{
try
{
Directory.CreateDirectory(DataFolder);
var tmp = SettingsPath + ".tmp";
File.WriteAllText(tmp, JsonSerializer.Serialize(settings, Options));
File.Copy(tmp, SettingsPath, true);
File.Delete(tmp);
}
catch
{
// 저장 실패는 무시 (다음 저장 때 다시 시도)
}
}
}
/// 작업 로그를 날짜별 파일에 추가 기록 (삭제 기능 없음)
public static class OperationLogFile
{
private static readonly object Sync = new object();
public static string Folder => Path.Combine(SettingsStore.DataFolder, "logs");
public static void Append(DateTime time, string text)
{
try
{
lock (Sync)
{
Directory.CreateDirectory(Folder);
var path = Path.Combine(Folder, time.ToString("yyyy-MM-dd") + ".log");
File.AppendAllText(path, $"[{time:yyyy-MM-dd HH:mm:ss}] {text}{Environment.NewLine}");
}
}
catch
{
// 기록 실패는 무시
}
}
}
}