<script setup>

import { ref, onMounted } from 'vue';
import { Button, FormGroup, TextInput } from 'pankow';
import { prettyBinarySize } from 'pankow/utils';
import AppsModel from '../../models/AppsModel.js';
import SystemModel from '../../models/SystemModel.js';

const appsModel = AppsModel.create();
const systemModel = SystemModel.create();

const props = defineProps([ 'app' ]);

const memoryLimitBusy = ref(false);
const memoryLimit = ref(0);
const currentMemoryLimit = ref(0);
const memoryTicks = ref([]);
const cpuQuotaBusy = ref(false);
const cpuQuota = ref(0);
const currentCpuQuota = ref(0);
const devicesBusy = ref(false);
const devicesError = ref('');
const devices = ref('');
const currentDevices = ref('');

async function onSubmitMemoryLimit() {
  memoryLimitBusy.value = true;

  const tmp = parseInt(memoryLimit.value);
  const limit = tmp === memoryTicks.value[0] ? 0 : tmp; // this will reset to app minimum

  const [error] = await appsModel.configure(props.app.id, 'memory_limit', { memoryLimit: limit });
  if (error) return console.error(error);

  // give polling some time
  setTimeout(() => memoryLimitBusy.value = false, 2000);
}

async function onSubmitCpuQuota() {
  cpuQuotaBusy.value = true;

  const [error] = await appsModel.configure(props.app.id, 'cpu_quota', { cpuQuota: parseInt(cpuQuota.value) });
  if (error) return console.error(error);

  currentCpuQuota.value = parseInt(cpuQuota.value);

  // give polling some time
  setTimeout(() => cpuQuotaBusy.value = false, 2000);
}

async function onSubmitDevices() {
  devicesBusy.value = true;

  const devs = {};
  devices.value.split(',').forEach(d => {
    if (!d.trim()) return;
    devs[d.trim()] = {};
  });

  const [error] = await appsModel.configure(props.app.id, 'devices', { devices: devs });
  if (error && error.status === 400) {
    devicesError.value = error.body.message;
    return devicesBusy.value = false;
  } else if (error) {
    return console.error(error);
  }

  // give polling some time
  setTimeout(() => devicesBusy.value = false, 2000);
}

onMounted(async () => {
  const [error, result] = await systemModel.memory();
  if (error) return console.error(error);

  cpuQuota.value = props.app.cpuQuota;
  currentCpuQuota.value = result.cpuQuota;
  devices.value = Object.keys(props.app.devices).join(', ');
  currentDevices.value = devices.value;

  memoryLimit.value = props.app.memoryLimit || props.app.manifest.memoryLimit || (256 * 1024 * 1024);
  currentMemoryLimit.value = memoryLimit.value;

  // create ticks starting from manifest memory limit. the memory limit here is just RAM
  memoryTicks.value = [];
  // we max system memory and current app memory for the case where the user configured the app on another server with more resources
  const nearest256m = Math.ceil(Math.max(result.memory, memoryLimit.value) / (256*1024*1024)) * 256 * 1024 * 1024;
  const startTick = props.app.manifest.memoryLimit || (256 * 1024 * 1024);

  // code below ensure we atleast have 2 ticks to keep the slider usable
  memoryTicks.value.push(startTick); // start tick
  for (var i = startTick * 2; i < nearest256m; i *= 2) memoryTicks.value.push(i);
  memoryTicks.value.push(nearest256m); // end tick
});

</script>

<template>
  <div>
    <FormGroup>
      <label for="memoryLimitInput">{{ $t('app.resources.memory.title') }} <sup><a href="https://docs.cloudron.io/apps/#memory-limit" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup> : <b>{{ prettyBinarySize(memoryLimit, 'Default (256 MiB)') }}</b></label>
      <p>{{ $t('app.resources.memory.description') }}</p>
      <input type="range" id="memoryLimitInput" v-model="memoryLimit" step="134217728" :min="memoryTicks[0]" :max="memoryTicks[memoryTicks.length-1]" list="memoryLimitTicks" />
      <datalist id="memoryLimitTicks">
        <option v-for="value of memoryTicks" :key="value" :value="value"></option>
      </datalist>
    </FormGroup>
    <br/>
    <Button @click="onSubmitMemoryLimit()" :loading="memoryLimitBusy" :disabled="memoryLimitBusy || memoryLimit === currentMemoryLimit || app.error || app.taskId" v-tooltip="app.error ? 'App is in error state' : (app.taskId ? 'App is busy' : '')">{{ $t('app.resources.memory.resizeAction') }}</Button>

    <hr/>

    <FormGroup>
      <label for="cpuQuotaInput">{{ $t('app.resources.cpu.title') }} <sup><a href="https://docs.cloudron.io/apps/#cpu-limit" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup> : <b>{{ cpuQuota + ' %' }}</b></label>
      <p>{{ $t('app.resources.cpu.description') }}</p>
      <input type="range" id="cpuQuotaInput" v-model="cpuQuota" step="1" min="1" max="100" list="cpuQuotaTicks" />
       <datalist id="cpuQuotaTicks">
        <option value="25"></option>
        <option value="50"></option>
        <option value="75"></option>
      </datalist>
    </FormGroup>
    <br/>
    <Button @click="onSubmitCpuQuota()" :loading="cpuQuotaBusy" :disabled="cpuQuotaBusy || cpuQuota === currentCpuQuota || app.error || app.taskId" v-tooltip="app.error ? 'App is in error state' : (app.taskId ? 'App is busy' : '')">{{ $t('app.resources.cpu.setAction') }}</Button>

    <hr/>

    <form @submit.prevent="onSubmitDevices()" autocomplete="off">
      <fieldset :disabled="devicesBusy || app.error || app.taskId">
        <input style="display: none;" type="submit" :disabled="devices === currentDevices"/>
        <FormGroup>
          <label for="devicesInput">Devices <sup><a href="https://docs.cloudron.io/apps/#devices" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
          <p>Comma serparated list of devices mounted into the app</p>
          <TextInput id="devicesInput" v-model="devices" placeholder="/dev/ttyUSB0, /dev/hidraw0, ..."/>
          <span class="text-danger" v-if="devicesError">{{ devicesError }}</span>
        </FormGroup>
      </fieldset>
    </form>
    <br/>
    <Button @click="onSubmitDevices()" :loading="devicesBusy" :disabled="devices === currentDevices || devicesBusy || app.error || app.taskId" tooltip-enable="app.error || app.taskId" uib-tooltip="{{ app.error ? 'App is in error state' : 'App is busy' }}">Set Devices</Button>
  </div>
</template>