using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using JJServiceManager.Remote;
namespace JJServiceManager
{
/// 설정 화면 (탭: 일반 / 원격 접속 허용 / 관리 대상 PC)
public sealed class SettingsWindow : Window
{
private readonly AppSettings _s;
// 일반
private readonly CheckBox _startup, _hotkey, _opLog, _shutdownButtons, _confirmLocal, _confirmRemote;
private readonly TextBox _hotkeyBox;
private readonly ComboBox _logMode, _esc;
private ModifierKeys _mods;
private Key _key;
// 원격 접속 허용
private readonly CheckBox _server, _activeListen, _allowView, _allowControl, _requireApproval;
private readonly ComboBox _serverMode;
private readonly TextBox _serverPort;
private readonly TextBlock _serverPortHint, _pwState, _serverInfo;
private readonly PasswordBox _pwd1, _pwd2;
private int _sshPort, _tcpPort;
private int _shownMode = -1;
// Passive 접속 (대상 PC 쪽)
private readonly ListBox _pmList;
private readonly TextBox _pmAddr, _pmCode, _pmPort;
private readonly ComboBox _pmMode;
private readonly TextBlock _pmResult;
private readonly ObservableCollection _pms = new ObservableCollection();
// 관리 대상 PC
private readonly CheckBox _manage;
private readonly ComboBox _passiveMode;
private readonly TextBox _passivePort;
private int _passiveSshPort, _passiveTcpPort;
private int _shownPassiveMode = -1;
private readonly ListBox _targets;
private readonly TextBox _addr, _hostname, _port, _code;
private readonly ComboBox _mode, _direction;
private readonly PasswordBox _pwdTarget;
private readonly TextBlock _pwTargetState, _test, _lblAddr;
private readonly FrameworkElement _lblMode, _lblPort, _lblCode, _pnlCode;
private readonly Button _btnTest;
private readonly ObservableCollection _items = new ObservableCollection();
/// 목록 표시용
private sealed class TargetItem : ObservableObject
{
public RemoteTarget T { get; }
public TargetItem(RemoteTarget t) => T = t;
public string Label => T.Label;
public string ModeText => T.Direction == ConnectDirection.Passive
? "Passive · 코드 " + T.AccessCode
: "Active · " + (T.Mode == RemoteMode.Ssh ? "SSH" : "지정 포트") + " " + T.Port;
public void Changed()
{
OnPropertyChanged(nameof(Label));
OnPropertyChanged(nameof(ModeText));
}
}
public SettingsWindow(AppSettings current)
{
_s = current;
Title = "설정" + AppInstance.TitleTag;
Width = 800;
Height = 720;
MinHeight = 560;
ResizeMode = ResizeMode.CanResize;
FontFamily = new FontFamily("Malgun Gothic");
FontSize = 13;
Background = Brushes2.Make("#FAFAFA");
WindowStartupLocation = WindowStartupLocation.CenterOwner;
ShowInTaskbar = false;
AppIcon.Apply(this);
var root = XamlLoader.LoadElement("Settings.xaml");
Content = root;
// ───────── 일반 ─────────
_startup = root.Find("chkStartup");
_hotkey = root.Find("chkHotkey");
_opLog = root.Find("chkOpLog");
_shutdownButtons = root.Find("chkShutdownButtons");
_confirmLocal = root.Find("chkConfirmLocal");
_confirmRemote = root.Find("chkConfirmRemote");
_hotkeyBox = root.Find("txtHotkey");
_logMode = root.Find("cmbLogMode");
_esc = root.Find("cmbEsc");
root.Find("txtDataPath").Text = "설정 파일: " + SettingsStore.SettingsPath
+ "\n작업 로그 파일: " + OperationLogFile.Folder;
_startup.IsChecked = current.RunAtStartup;
_hotkey.IsChecked = current.HotkeyEnabled;
_opLog.IsChecked = current.ShowOperationLog;
_shutdownButtons.IsChecked = current.ShowShutdownButtons;
_confirmLocal.IsChecked = current.ConfirmLocalStartStop;
_confirmRemote.IsChecked = current.ConfirmRemoteStartStop;
_logMode.SelectedIndex = (int)current.LogWindowMode;
_esc.SelectedIndex = (int)current.EscAction;
_mods = (ModifierKeys)current.HotkeyModifiers;
_key = (Key)current.HotkeyKey;
ShowHotkey();
// 단축키: 클릭 후 직접 눌러서 지정
_hotkeyBox.GotKeyboardFocus += (s, e) => _hotkeyBox.Background = Brushes2.Make("#FFF8E1");
_hotkeyBox.LostKeyboardFocus += (s, e) => { _hotkeyBox.Background = Brushes2.Make("#FAFAFA"); ShowHotkey(); };
_hotkeyBox.PreviewKeyDown += OnHotkeyKeyDown;
// ───────── 원격 접속 허용 ─────────
_server = root.Find("chkServer");
_activeListen = root.Find("chkActiveListen");
_allowView = root.Find("chkAllowView");
_allowControl = root.Find("chkAllowControl");
_requireApproval = root.Find("chkRequireApproval");
_serverMode = root.Find("cmbServerMode");
_serverPort = root.Find("txtServerPort");
_serverPortHint = root.Find("txtServerPortHint");
_pwd1 = root.Find("pwdServer");
_pwd2 = root.Find("pwdServer2");
_pwState = root.Find("txtPwState");
_serverInfo = root.Find("txtServerInfo");
_sshPort = current.RemoteServerSshPort;
_tcpPort = current.RemoteServerTcpPort;
_server.IsChecked = current.RemoteServerEnabled;
_activeListen.IsChecked = current.RemoteServerActiveListen;
_allowView.IsChecked = current.RemoteAllowView;
_allowControl.IsChecked = current.RemoteAllowControl;
_requireApproval.IsChecked = current.RemoteRequireApproval;
_serverMode.SelectionChanged += (s, e) => OnServerModeChanged();
_serverMode.SelectedIndex = (int)current.RemoteServerMode;
_pwState.Text = string.IsNullOrEmpty(current.RemotePasswordHash)
? "비밀번호가 설정되어 있지 않습니다. 원격 접속을 허용하려면 입력하세요."
: "비밀번호가 설정되어 있습니다. 바꿀 때만 입력하세요.";
// 제어 허용은 화면 보기가 켜져 있어야 함
_allowView.Checked += (s, e) => _allowControl.IsEnabled = true;
_allowView.Unchecked += (s, e) => { _allowControl.IsChecked = false; _allowControl.IsEnabled = false; };
_allowControl.IsEnabled = _allowView.IsChecked == true;
UpdateServerInfo();
// Passive 접속 (이 PC → 관리 PC)
_pmList = root.Find("lstPassive");
_pmAddr = root.Find("txtPmAddr");
_pmCode = root.Find("txtPmCode");
_pmPort = root.Find("txtPmPort");
_pmMode = root.Find("cmbPmMode");
_pmResult = root.Find("txtPmResult");
foreach (var m in current.PassiveManagers) _pms.Add(m.Clone());
_pmList.ItemsSource = _pms;
_pmList.SelectionChanged += (s, e) => ShowPm(_pmList.SelectedItem as PassiveManager);
_pmMode.SelectionChanged += (s, e) =>
{
if (_pmPort.Text == "" || _pmPort.Text == "9990" || _pmPort.Text == "2224")
_pmPort.Text = _pmMode.SelectedIndex == 0 ? "2224" : "9990";
};
ClearPmForm();
root.Find