--추가 기능 이름 (대문자)
local addonName = "CAMPWARP";
local addonNameLower = string.lower(addonName);
--작성자 이름
local author = "AUTHOR";

--추가 기능에서 사용하는 공간을 만들었습니다. 다음 파일의 범위에서 전역 변수 g 액세스 가능
_G["ADDONS"] = _G["ADDONS"] or {};
_G["ADDONS"][author] = _G["ADDONS"][author] or {};
_G["ADDONS"][author][addonName] = _G["ADDONS"][author][addonName] or {};
local g = _G["ADDONS"][author][addonName];

--설정 파일 저장 위치
g.settingsFileLoc = string.format("../addons/%s/settings.json", addonNameLower);

--라이브러리 로드
local acutil = require('acutil');

--기본 설정
if not g.loaded then
  g.settings = {
    --활성화/비활성화
    enable = true,
    --프레임 표시 위치
    position = {
      x = 0,
      y = 0
    }
  };
end

--lua 읽을 때 메시지
CHAT_SYSTEM(string.format("%s 애드온 실행! ~'ㅅ')~ ", addonName));
CHAT_SYSTEM(string.format("<CAMP WARP 사용법 1> 파티 상태로 /cw 또는 /campwarp : 캠프로 이동"));
CHAT_SYSTEM(string.format("<CAMP WARP 사용법 2> /cw 숫자 : 파티원의 캠프로 이동"));

function CAMPWARP_SAVESETTINGS()
  acutil.saveJSON(g.settingsFileLoc, g.settings);
end

--맵로드시 처리 (1번)
function CAMPWARP_ON_INIT(addon, frame)
  g.addon = addon;
  g.frame = frame;
  frame:ShowWindow(0);
  acutil.slashCommand("/"..addonNameLower, CAMPWARP_PROCESS_COMMAND);
  acutil.slashCommand("/cw", CAMPWARP_PROCESS_COMMAND);

  if not g.loaded then
    local t, err = acutil.loadJSON(g.settingsFileLoc, g.settings);
    if err then
      --설정 파일 읽기 실패시 처리
      CHAT_SYSTEM(string.format("[%s] 설정 파일을 불러올 수 없습니다.", addonName));
    else
      --설정 파일 읽기 성공시 처리
      g.settings = t;
    end
    g.loaded = true;
  end

  --설정 파일 저장 처리
  CAMPWARP_SAVESETTINGS();
  --메시지 수신 등록 처리
  addon:RegisterMsg("GAME_START_3SEC", "CAMPWARP_3SEC");

  --컨텍스트 메뉴
  frame:SetEventScript(ui.RBUTTONDOWN, "CAMPWARP_CONTEXT_MENU");
  --드래그
  frame:SetEventScript(ui.LBUTTONUP, "CAMPWARP_END_DRAG");
end

function CAMPWARP_3SEC()
  --맵 이동 직후 캠프 정보를 얻을 수 없기 때문에 3초 동안 기다립니다.
  local frame = g.frame;
  --프레임 초기화 처리
  CAMPWARP_INIT_FRAME(frame);

  --다시보기 처리
  if g.settings.enable then
    frame:ShowWindow(1);
  else
    frame:ShowWindow(0);
  end
  --Move는 잘되지 않아서 OffSet를 사용하는 ...
  frame:Move(0, 0);
  frame:SetOffset(g.settings.position.x, g.settings.position.y);
end

function CAMPWARP_INIT_FRAME(frame)
  --XML에 기재하면 디자인 조정시 클라이언트 다시 시작해야하기 때문에 lua에 쓰는 것을 추천합니다
  local iconSize = 45;
  local title = frame:CreateOrGetControl("richtext", "title", 5, 3, 0, 15);
  tolua.cast(title, "ui::CRichText");
  title:SetText(string.format("{@st62}Camp Warp{/}"));
  title:EnableHitTest(0);

  local camps = CAMPWARP_GET_CAMPLIST();
  for i, camp in ipairs(camps) do
    local picture = frame:CreateOrGetControl("picture", "picture_"..i, (i-1) * iconSize + 10, 15, iconSize, iconSize);
    tolua.cast(picture, "ui::CPicture");
    picture:SetEnableStretch(1);
    picture:SetImage("minimap_man_market");
    picture:SetEventScript(ui.LBUTTONUP, "CAMPWARP_EXEC_WARP("..i..")");
    picture:SetTextTooltip(camp.name..":"..camp.map.Name);
    
    local name = picture:CreateOrGetControl("richtext", "name_"..i, (i-1) * 0, 0, iconSize, 15);
    tolua.cast(name, "ui::CRichText");
    name:EnableHitTest(0);
    name:EnableResizeByText(0);
    name:SetText(string.format("{@st62}%s{/}", camp.name));
    name:SetGravity(ui.LEFT, ui.BOTTOM);
  end

  if #camps > 0 then
    local width = iconSize * #camps + 10 < title:GetWidth()+5 and title:GetWidth()+5 or iconSize * #camps + 10;
    frame:Resize(width, iconSize + 15);
  else
    frame:Resize(title:GetWidth()+5, title:GetHeight()+5);
  end
end

--컨텍스트 메뉴 표시 처리
function CAMPWARP_CONTEXT_MENU(frame, msg, clickedGroupName, argNum)
  local context = ui.CreateContextMenu("CAMPWARP_RBTN", "CampWarp", 0, 0, 300, 100);
  ui.AddContextMenuItem(context, "Hide", "CAMPWARP_TOGGLE_FRAME()");
  context:Resize(300, context:GetHeight());
  ui.OpenContextMenu(context);
end

--표시 숨기기 전환 처리
function CAMPWARP_TOGGLE_FRAME()
  if g.frame:IsVisible() == 0 then
    --숨기기->보기
    g.frame:ShowWindow(1);
    g.settings.enable = true;
  else
    --表示->非表示
    g.frame:ShowWindow(0);
    g.settings.enable = false;
  end

  CAMPWARP_SAVESETTINGS();
end

--フレーム場所保存処理
function CAMPWARP_END_DRAG()
  g.dragging = false;
  g.settings.position.x = g.frame:GetX();
  g.settings.position.y = g.frame:GetY();
  CAMPWARP_SAVESETTINGS();
end

--チャットコマンド処理（acutil使用時）
function CAMPWARP_PROCESS_COMMAND(command)
  local cmd = "";

  if #command > 0 then
    cmd = table.remove(command, 1);
    cmd = tonumber(cmd);
    if cmd then
      CAMPWARP_EXEC_WARP(cmd);
      return;
    end
  else
    CAMPWARP_EXEC_WARP(1);
    return;
  end

  CHAT_SYSTEM("[CAMPWARP] 잘못된 명령어입니다.");
end

function CAMPWARP_EXEC_WARP(number)
  number = number or 1;
  local camps = CAMPWARP_GET_CAMPLIST()
  local member = camps[number];
  if member ~= nil then
    local message = string.format("%s 님의 캠프가 설치된 %s 쪽으로 이동합니다.", member.name, member.map.Name);
    CHAT_SYSTEM(message);
    MOVETOCAMP(member.aid);
    return;
  end
  CHAT_SYSTEM("[CAMPWARP] 캠프를 찾을 수 없습니다.");
end

function CAMPWARP_GET_CAMPLIST()
  local list = session.party.GetPartyMemberList(PARTY_NORMAL);
  local count = list:Count();
  local campCount = 0;
  local camps = {};
  for i = 0 , count - 1 do
    local partyMemberInfo = list:Element(i);
    local map = GetClassByType("Map", partyMemberInfo.campMapID);
    if  nil ~= map then
      table.insert(camps, {name=partyMemberInfo:GetName(), aid = partyMemberInfo:GetAID(), map = map});
    end
  end
  return camps;
end
