// Weapon Swap Indicator - D2RMM smart patch
// Faithfully implements the verified clean data mod without replacing vanilla hudpanelhd.json or sounds.txt wholesale.

var PANEL_NAME = 'weaponswapindicator';
var TIMER_NAME = 'WeaponSwapIndicator_Open';

function toByteText(value, fallback, label) {
  var raw = value;
  if (raw === undefined || raw === null || String(raw).trim() === '') {
    console.log(label + ' is empty. Using default ' + fallback + '.');
    return String(fallback);
  }

  var num = Number(String(raw).trim());
  if (!isFinite(num)) {
    console.log(label + ' is not a number: ' + raw + '. Using default ' + fallback + '.');
    return String(fallback);
  }

  num = Math.round(num);
  if (num < 0) {
    console.log(label + ' is below 0. Clamped to 0.');
    num = 0;
  }
  if (num > 255) {
    console.log(label + ' is above 255. Clamped to 255.');
    num = 255;
  }
  return String(num);
}

function toPanelPriority(value, fallback, label) {
  var raw = value;
  if (raw === undefined || raw === null || String(raw).trim() === '') {
    console.log(label + ' is empty. Using default ' + fallback + '.');
    return fallback;
  }

  var num = Number(String(raw).trim());
  if (!isFinite(num)) {
    console.log(label + ' is not a number: ' + raw + '. Using default ' + fallback + '.');
    return fallback;
  }

  return num;
}

// 1) Add non-vanilla assets/layouts without readJson() on missing files.
// The vanilla front HUD panel uses priority 100 by default.
// The weapon swap indicator panels use priority 101 by default so they render above the front HUD panel.
// Advanced users can override these priorities; higher numbers render above lower numbers.
var frontPanelSpriteType = config.frontPanelSpriteType === 'full' ? 'full' : 'armband';
var frontPanelSpritePrefix = 'hd\\global\\ui\\panel\\hud_02\\front_panel_' + frontPanelSpriteType + '_';
var frontPanelSpriteDestPrefix = 'hd\\global\\ui\\panel\\hud_02\\front_panel_';
var frontPanelControllerSpritePrefix = 'hd\\global\\ui\\panel\\hud_02\\front_panel_' + frontPanelSpriteType + '_controller_';
var frontPanelControllerDestPrefix = 'hd\\global\\ui\\panel\\hud_02\\front_panel_controller_';

D2RMM.copyFile(frontPanelSpritePrefix + 'left.sprite', frontPanelSpriteDestPrefix + 'left.sprite', true);
D2RMM.copyFile(frontPanelSpritePrefix + 'left.lowend.sprite', frontPanelSpriteDestPrefix + 'left.lowend.sprite', true);
D2RMM.copyFile(frontPanelSpritePrefix + 'right.sprite', frontPanelSpriteDestPrefix + 'right.sprite', true);
D2RMM.copyFile(frontPanelSpritePrefix + 'right.lowend.sprite', frontPanelSpriteDestPrefix + 'right.lowend.sprite', true);

// Controller uses separate sprite source filenames and copies the selected controller artwork to fixed runtime names.
D2RMM.copyFile(frontPanelControllerSpritePrefix + 'left.sprite', frontPanelControllerDestPrefix + 'left.sprite', true);
D2RMM.copyFile(frontPanelControllerSpritePrefix + 'left.lowend.sprite', frontPanelControllerDestPrefix + 'left.lowend.sprite', true);
D2RMM.copyFile(frontPanelControllerSpritePrefix + 'right.sprite', frontPanelControllerDestPrefix + 'right.sprite', true);
D2RMM.copyFile(frontPanelControllerSpritePrefix + 'right.lowend.sprite', frontPanelControllerDestPrefix + 'right.lowend.sprite', true);

function makeWeaponSwapIndicatorLayout(panelPriority, panelRect, imageX, imageY, spritePrefix) {
  return {
    type: 'PlayerInventoryPanel',
    name: PANEL_NAME,
    fields: {
      priority: panelPriority,
      anchor: { x: 0.5, y: 1 },
      rect: panelRect
    },
    children: [
      {
        type: 'ButtonWidget',
        name: 'Close',
        fields: {
          rect: { x: 0, y: 2500 },
          filename: 'PANEL\\closebtn_4x',
          onClickMessage: 'PanelManager:ClosePanel:' + PANEL_NAME,
          acceptsEscKeyEverywhere: false
        }
      },
      {
        type: 'ImageWidget',
        name: 'background_right_arm_selected',
        fields: {
          rect: { x: imageX, y: imageY, scale: 1.0 },
          filename: spritePrefix + 'left'
        }
      },
      {
        type: 'ImageWidget',
        name: 'background_right_arm',
        fields: {
          rect: { x: imageX, y: imageY, scale: 1.0 },
          filename: spritePrefix + 'right'
        }
      }
    ]
  };
}

var DEFAULT_FRONT_PANEL_PRIORITY = 100;
var DEFAULT_SWAP_PANEL_PRIORITY = 101;
var frontPanelPriority = DEFAULT_FRONT_PANEL_PRIORITY;
if (config.enableAdvancedFrontPanelPriority) {
  frontPanelPriority = toPanelPriority(config.frontPanelPriority, DEFAULT_FRONT_PANEL_PRIORITY, '(고급사용자) 프론트패널 우선순위');
}

var swapPanelPriority = DEFAULT_SWAP_PANEL_PRIORITY;
if (config.enableAdvancedPanelPriority) {
  swapPanelPriority = toPanelPriority(config.panelPriority, DEFAULT_SWAP_PANEL_PRIORITY, '(고급사용자) 스왑패널 우선순위');
}

D2RMM.writeJson(
  'global\\ui\\layouts\\weaponswapindicatorhd.json',
  makeWeaponSwapIndicatorLayout(
    swapPanelPriority,
    { x: -1454, y: -412, width: 2952, height: 764 },
    34,
    0,
    'PANEL/HUD_02/front_panel_'
  )
);

// Controller HUD uses a wider front panel. Keep it independent from the keyboard/mouse layout.
// Controller artwork is based on the vanilla Controller/HUD/HUDBase placement.
D2RMM.writeJson(
  'global\\ui\\layouts\\controller\\weaponswapindicatorhd.json',
  makeWeaponSwapIndicatorLayout(
    swapPanelPriority,
    { x: -1473, y: -417, width: 2952, height: 764 },
    -121,
    7,
    'PANEL/HUD_02/front_panel_controller_'
  )
);

// 2) Smart-patch vanilla hudpanelhd.json.
var hudPath = 'global\\ui\\layouts\\hudpanelhd.json';
var hud = D2RMM.readJson(hudPath);

if (!hud.fields) {
  hud.fields = {};
}

// Keep the vanilla front HUD panel priority at 100 by default.
hud.fields.priority = frontPanelPriority;

if (!hud.children) {
  hud.children = [];
}

// Prevent duplicate timers on re-install.
var cleanedChildren = [];
for (var i = 0; i < hud.children.length; i++) {
  var child = hud.children[i];
  var msg = child && child.fields ? child.fields.message : '';
  var name = child ? child.name : '';

  if (name === TIMER_NAME) {
    continue;
  }
  if (msg === 'PanelManager:OpenPanel:' + PANEL_NAME) {
    continue;
  }

  cleanedChildren.push(child);
}
hud.children = cleanedChildren;

hud.children.push({
  type: 'TimerWidget',
  name: TIMER_NAME,
  fields: {
    time: 0,
    message: 'PanelManager:OpenPanel:' + PANEL_NAME
  }
});

D2RMM.writeJson(hudPath, hud);

// 3) Optional smart-patch for weapon swap sound.
// OFF means: do not copy the replacement FLAC and do not modify sounds.txt, so vanilla behavior is preserved.
if (config.enableSwapSound) {
  D2RMM.copyFile('hd\\global\\sfx\\cursor\\cursor_swap_weapon_hd.flac', 'hd\\global\\sfx\\cursor\\cursor_swap_weapon_hd.flac', true);

  var volumeMin = toByteText(config.swapSoundVolumeMin, 100, '무기스왑음 최소볼륨');
  var volumeMax = toByteText(config.swapSoundVolumeMax, 100, '무기스왑음 최대볼륨');
  var priority = toByteText(config.swapSoundPriority, 255, '무기스왑음 우선순위');

  var soundsPath = 'global\\excel\\sounds.txt';
  var sounds = D2RMM.readTsv(soundsPath, { removeCarriageReturns: true });
  var foundSwapSound = false;

  for (var r = 0; r < sounds.rows.length; r++) {
    var row = sounds.rows[r];
    if (row.Sound === 'cursor_swap_weapon_hd') {
      row.FileName = 'cursor\\cursor_swap_weapon_hd.flac';
      row['Volume Min'] = volumeMin;
      row['Volume Max'] = volumeMax;
      row['Fade In'] = '0';
      row['Fade Out'] = '0';
      row.Priority = priority;
      foundSwapSound = true;
      break;
    }
  }

  if (!foundSwapSound) {
    throw new Error('cursor_swap_weapon_hd row was not found in global\\excel\\sounds.txt');
  }

  D2RMM.writeTsv(soundsPath, sounds, { addCarriageReturns: true });
}
