// Modules to control application life and create native browser window
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
const fs = require("fs")
if (process.platform === 'linux') {
  app.commandLine.appendSwitch('enable-transparent-visuals');
  app.commandLine.appendSwitch('disable-gpu');
}

var debug_flag = false;
//debug_flag = true;

//二重起動の防止
const doubleboot = app.requestSingleInstanceLock();
if(!doubleboot){
  app.quit();
}

// ウィンドウ位置保存用ファイル
let boundsFile = path.join(
  app.getPath('userData'), 'bounds.json'
);
//-> 保存しておいたウィンドウ位置の取得
let bounds = {};
try {
  bounds = JSON.parse(
    fs.readFileSync(boundsFile, 'utf8')
  );
} catch (e) {
  bounds = {x: 500, y: 500};
}

// 設定保存用ファイル
let configFile = path.join(
  app.getPath('userData'), 'config.json'
);
//-> 保存しておいた設定の取得
let USERCONF = {};
USERCONF_init = {
  ghost: "neko",// ゴースト
  name: false,// ユーザの名前
  teiji: "",// ユーザの定時
  rate: 0,// 好感度
  width: 140,// ゴーストの横サイズ
  alwaysOnTop: true,// 常に前面に出すか
  interval: 3000// 会話のインターバル
};
try {
  USERCONF = JSON.parse(
    fs.readFileSync(configFile, 'utf8')
  );
} catch (e) {
  USERCONF = JSON.parse(JSON.stringify(USERCONF_init));
}
//console.log(USERCONF);

let mainWindow, balloonWindow, menuWindow, inputWindow, webWindow;
function createWindow () {
  mainWindow = new BrowserWindow(Object.assign(
    bounds, {
      width: (debug_flag ? 800 : USERCONF.width),
      height: (debug_flag ? 600 : USERCONF.width),
      transparent: true,
      frame: debug_flag,
      toolbar: false,
      hasShadow: false,
      show: false,
      resizable: false,
      icon: path.join(__dirname, 'ghost', "neko", "asset", "default.png"),
      alwaysOnTop: USERCONF.alwaysOnTop,
      useContentSize: true,
      webPreferences: {
        nodeIntegration: true,
        preload: path.join(__dirname, 'preload', 'preload.js'),
        contextIsolation: true
      }
    }))
  mainWindow.loadFile('index.html')
  mainWindow.once("ready-to-show", function() {
    mainWindow.show();
  });
  // 閉じるとき
  mainWindow.on("close", function() {
    balloonWindow.destroy();
    menuWindow.destroy();
    inputWindow.destroy();
    webWindow.destroy()
    app.quit();
  });
  // 最小化するとき
  mainWindow.on("minimize", function() {
    if (!balloonWindow.isMinimized()) {
      balloonWindow.minimize();
    }
    menuWindow.hide();
    inputWindow.hide();
    webWindow.hide();
  });
  // 最小化から戻るとき
  mainWindow.on("restore", function() {
    if (balloonWindow.isMinimized()) {
      balloonWindow.restore();
    }
  });
  // Open the DevTools.
  if (debug_flag) {
    mainWindow.webContents.openDevTools()
  }
}

function createBalloonWindow () {
  // Create the browser window.
  balloonWindow = new BrowserWindow(Object.assign(
    bounds, {
      width: (debug_flag ? 800 : 140),
      height: (debug_flag ? 500 : 140),
      transparent: !debug_flag,
      frame: debug_flag,
      toolbar: false,
      hasShadow: false,
      resizable: debug_flag,
      icon: path.join(__dirname, 'ghost', "neko", "asset", "default.png"),
      //icon: path.join(__dirname, 'icon/icon.png'),
      alwaysOnTop: USERCONF.alwaysOnTop,
      useContentSize: true,
      parent: mainWindow,
      webPreferences: {
        nodeIntegration: true,
        preload: path.join(__dirname, 'preload', 'preload_balloon.js'),
        contextIsolation: true
      }
    }))
  balloonWindow.setIgnoreMouseEvents(true);
  balloonWindow.loadFile('balloon.html')
  // バルーンが閉じたとき
  balloonWindow.on("close", function() {
    mainWindow.destroy();
    menuWindow.destroy();
    inputWindow.destroy();
    webWindow.destroy();
    app.quit();
  })
  // バルーンが最小化したとき
  balloonWindow.on("minimize", function() {
    if (!mainWindow.isMinimized()) {
      mainWindow.minimize();
    }
    menuWindow.hide();
    inputWindow.hide();
    webWindow.hide();
  });
  // バルーンが最小化から戻ったとき
  balloonWindow.on("restore", function() {
    if (mainWindow.isMinimized()) {
      mainWindow.restore();
    }
  });
  if (debug_flag) {
    balloonWindow.webContents.openDevTools()
  }
}

function createMenuWindow () {
  menuWindow = new BrowserWindow({
    width: (debug_flag ? 1400 : 300),
    height: 400,
    transparent: false,
    frame: true,
    toolbar: false,
    hasShadow: false,
    show: true,
    resizable: false,
    icon: path.join(__dirname, 'ghost', "neko", "asset", "default.png"),
    //icon: path.join(__dirname, 'icon/icon.png'),
    alwaysOnTop: USERCONF.alwaysOnTop,
    useContentSize: true,
    parent: mainWindow,
    webPreferences: {
      nodeIntegration: true,
      preload: path.join(__dirname, "preload", 'preload_menu.js'),
      contextIsolation: true
    }
  });
  menuWindow.setMenu(null);
  menuWindow.loadFile('menu.html');
  menuWindow.once("ready-to-show", function() {
    menuWindow.hide();
    balloonWindow.show();
  });
  menuWindow.on("close", function(e) {
    e.preventDefault();
    menuWindow.hide();
  });
  if (debug_flag) {
    menuWindow.webContents.openDevTools()
  }
}

function createInputWindow () {
  inputWindow = new BrowserWindow({
    width: (debug_flag ? 800 : 230),
    height: (debug_flag ? 800 : 60),
    transparent: false,
    frame: true,
    toolbar: false,
    hasShadow: false,
    show: false,
    resizable: false,
    icon: path.join(__dirname, 'ghost', "neko", "asset", "default.png"),
    //icon: path.join(__dirname, 'icon/icon.png'),
    alwaysOnTop: USERCONF.alwaysOnTop,
    useContentSize: true,
    parent: mainWindow,
    webPreferences: {
      nodeIntegration: true,
      preload: path.join(__dirname, 'preload', 'preload_input.js'),
      contextIsolation: true
    }
  });
  inputWindow.loadFile('input.html')
  inputWindow.setMenu(null);

  inputWindow.on("close", function(e) {
    e.preventDefault();
    inputWindow.hide();
  })
  inputWindow.on("minimize", function() {
    inputWindow.hide();
  });
  inputWindow.on("show", function() {
    inputWindow.focus();
  })
  if (debug_flag) {
    inputWindow.webContents.openDevTools()
  }
}


function createWebWindow () {
  webWindow = new BrowserWindow({
    width: (debug_flag ? 800 : 500),
    height: (debug_flag ? 800 : 600),
    transparent: false,
    frame: true,
    toolbar: false,
    hasShadow: false,
    show: false,
    resizable: true,
    icon: path.join(__dirname, 'ghost', "neko", "asset", "default.png"),
    //icon: path.join(__dirname, 'icon/icon.png'),
    alwaysOnTop: USERCONF.alwaysOnTop,
    useContentSize: true,
    parent: mainWindow,
    webPreferences: {
      nodeIntegration: true,
      //preload: path.join(__dirname, 'preload', 'preload_web.js'),
      contextIsolation: true
    }
  });
  webWindow.setMenu(null);

  webWindow.on("close", function(e) {
    e.preventDefault();
    webWindow.hide();
  })
  webWindow.on("minimize", function() {
    webWindow.hide();
  });
  webWindow.on("show", function() {
    webWindow.focus();
  })
  if (debug_flag) {
    webWindow.webContents.openDevTools()
  }
}

// [実行] =====================================

app.whenReady().then(() => {
  setTimeout(function() {
    // window作成 ---------------------
    createWindow();
    createBalloonWindow();
    createMenuWindow();
    createInputWindow();
    createWebWindow();
    // 設定 ---------------------------
    // バルーンと入力欄の追従
    setInterval(function() {
      var bbb = inputWindow.getBounds();
      var bb = balloonWindow.getBounds();
      var b = mainWindow.getBounds();
      bb.width = 300;
      bb.heght = 200;
      bb.x = b.x;
      bb.y = b.y - bb.height;
      balloonWindow.setBounds(bb);
      inputWindow.setPosition(b.x, b.y - bbb.height - 60);
    }, 500);
    // 好感度
    setInterval(function() {
      USERCONF.rate++;
    }, 3600000);
  }, 1000);
  // app.on('activate', function () {
  //   if (BrowserWindow.getAllWindows().length === 0) createWindow()
  // })
})


// [IPC ghost] ======================================

// main 起動フラグ --> main: ghostの種類と横幅
ipcMain.once("ghost-ready-message", (e, arg) => {
  e.reply("ghost-ready-reply", JSON.stringify(
    {ghost: USERCONF.ghost, width: USERCONF.width}
  ));
});

// ゴーストの横幅と縦幅取得
ipcMain.on("ghost-size-message", (e, arg) => {
  var b = mainWindow.getContentBounds();
  bounds.x = b.x;
  bounds.y = b.y;
  if (!debug_flag) {
    mainWindow.setContentBounds(Object.assign(bounds, JSON.parse(arg)));
  }
  //e.reply("ghostsize-reply", "ghostsize : " + arg)
});

ipcMain.on("ghost-console-message", (e, arg) => {
  console.log(arg);
});

// [IPC balloon] ======================================

// balloon 起動フラグ --> balloon: ghostの種類と横幅
ipcMain.once("balloon-ready-message", (e, arg) => {
  e.reply("balloon-ready-reply", JSON.stringify({
    ghost: USERCONF.ghost,
    width: USERCONF.width,
    interval: USERCONF.interval,
    username: USERCONF.name,
    teiji: USERCONF.teiji
  }));
});

// talk時のアセット受信 --> main: アセット情報
ipcMain.on("talk-asset-message", (event, arg) => {
  mainWindow.webContents.send("ghost-asset-message", arg);
});


// [IPC menu] ======================================

// menu 起動フラグ --> menu: 横幅
ipcMain.once("menu-ready-message", (e, arg) => {
  e.reply("menu-ready-reply", JSON.stringify({
    width: USERCONF.width,
    interval: USERCONF.interval,
    ghost: USERCONF.ghost,
    name: USERCONF.name,
    teiji: USERCONF.teiji
  }));
});
// 本当に準備できるまで表示させない
ipcMain.on("menu-openready-message", (e, arg) => {
  mainWindow.webContents.send("menu-ok-message", "1");
  ipcMain.on("menu-open-message", (event, arg) => {
    menuWindow.show();
  });
});

// 設定でサイズが変更されたとき
ipcMain.on("userconf-width-change-message", (e, arg) => {
  USERCONF.width = +arg;
  mainWindow.webContents.send("ghost-ready-reply",
                              JSON.stringify(
                                {ghost: USERCONF.ghost, width: USERCONF.width}
                              ));
  balloonWindow.webContents.send("confchange-message", "サイズを " + USERCONF.width + " に変更したよ！");
});
// 設定で喋り頻度が変更されたとき
ipcMain.on("userconf-interval-change-message", (e, arg) => {
  USERCONF.interval = +arg;
  balloonWindow.webContents.send("interval-change-message",
                                 JSON.stringify(
                                   {interval: USERCONF.interval}
                                 ));
  balloonWindow.webContents.send("confchange-message", "喋り頻度を " + USERCONF.interval + " に変更したよ！");
});
// 設定で定時が変更されたとき
ipcMain.on("userconf-teiji-change-message", (e, arg) => {
  USERCONF.teiji = arg;
  balloonWindow.webContents.send("teiji-change-message",
                                 JSON.stringify(
                                   {teiji: USERCONF.teiji}
                                 ));
  balloonWindow.webContents.send("confchange-message", "定時を " + USERCONF.teiji + " に変更したよ！");
});
// 設定でキャラが変更されたとき
ipcMain.on("userconf-ghost-change-message", (e, arg) => {
  USERCONF.ghost = arg;
  mainWindow.webContents.send("ghost-ready-reply",
                              JSON.stringify(
                                {ghost: USERCONF.ghost, width: USERCONF.width}
                              ));
  balloonWindow.webContents.send("confchange-message", "キャラクターを " + USERCONF.ghost + " に変更したよ！");
});
// 設定で名前が変更されたとき
ipcMain.on("userconf-name-change-message", (e, arg) => {
  if (USERCONF.name.length == 0) {
    USERCONF.name = false;
  } else {
    USERCONF.name = arg;
  }
  balloonWindow.webContents.send(
    "username-change-message",
    JSON.stringify({username: USERCONF.name})
  );
  if (USERCONF.name) {
    balloonWindow.webContents.send("confchange-message", USERCONF.name + "、よろしくね！");
  } else {
    balloonWindow.webContents.send("confchange-message", '名前が無くなった…(´・ω・`)');
  }
});


// [IPC input] ======================================

// input 起動フラグ --> input: --
ipcMain.once("input-ready-message", (e, arg) => {
  var b = inputWindow.getContentBounds();
  b.height = 30;
  if (!debug_flag) {
    inputWindow.setContentBounds(Object.assign(b));
  }
});
ipcMain.on("input-open-message", (event, arg) => {
  inputWindow.show();
  inputWindow.webContents.send("input-focus-message", "1");
});

ipcMain.on("input-message", (event, arg) => {
  balloonWindow.webContents.send("userinput-message", arg);
  inputWindow.hide();
});

// [IPC web] ===========================================

ipcMain.on("web-access-message", (e, arg) => {
  webWindow.loadURL(arg);
  webWindow.show();
});


// [終了] ===========================================

ipcMain.on("app-quit-message", (event, arg) => {
  app.quit();
});

app.on('before-quit', function() {
  var b = mainWindow.getBounds();
  bounds.x = b.x;
  bounds.y = b.y;
  fs.writeFileSync(
    boundsFile, JSON.stringify(bounds)
  );
  fs.writeFileSync(
    configFile, JSON.stringify(USERCONF)
  );
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
