<template>
  <div class="diffusion">
    <h1>
      <img
        id="logo_img"
        :src="config.base.easyDiffusion + '/media/images/icon-512x512.png'"
      />
      <span style="vertical-align: middle">AI绘图</span>
    </h1>
    <el-row class="body">
      <el-col :span="8">
        <div class="main left">
          <p class="label">输入描述<small>（建议输入英文）</small></p>
          <el-input
            v-model="textarea"
            :rows="2"
            type="textarea"
            placeholder="请输入描述内容"
          />
          <p class="label">初始图片 (img2img) <small>(可选)</small></p>
          <input
            type="file"
            style="position: absolute; left: -100%"
            name="file"
            id="file"
            accept="image/*"
            @change="selectfile"
          />
          <image-ele
            v-if="fileInput.file"
            :file="fileInput"
            @close="closeFunc"
            @draw="draw"
          />
          <label
            for="file"
            class="dark"
            v-if="!fileInput.file"
            style="
              background-color: #202225;
              padding: 3px 8px;
              font-size: 0.9em;
              border-radius: 3px;
            "
          >
            <el-icon><FolderOpened /></el-icon>
            选择
          </label>

          <span
            for="file"
            class="dark"
            v-if="!fileInput.file"
            style="
              background-color: #202225;
              padding: 3px 8px;
              font-size: 0.9em;
              border-radius: 3px;
              margin-left: 3px;
            "
            @click="draw"
          >
            <el-icon><EditPen /></el-icon>
            绘制
          </span>

          <p class="label" v-if="Object.keys(selectObject).length">
            图像修改器
          </p>
          <img-com
            v-for="(v, i) in selectObject || {}"
            :key="i + 'select'"
            :imgUrl="v.previews[selectType].path"
            :text="v.modifier"
            :isSelect="true"
            @click="() => delectSelect(i)"
          />
          <el-button
            type="primary"
            size="large"
            color="#4d5bff"
            style="display: block; width: 100%; margin-top: 1em"
            @click="createDr"
            :loading="loading"
          >
            生成图片
          </el-button>
          <div class="line"></div>
         <el-collapse>
            <el-collapse-item>
              <template #title>
                <div class="collapseTitle">
                  <el-icon size="11pt">
                    <Plus />
                  </el-icon>
                  图像设置
                </div>
              </template>
              <!-- <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">种子：</div>
                </el-col>
                <el-col :span="20">
                  <el-input
                    size="small"
                    style="width: 5em; margin-right: 3px"
                    v-model="obj.zhongzi"
                    :disabled="obj.zhongzisuiji"
                  />
                  <el-switch
                    size="small"
                    v-model="obj.zhongzisuiji"
                    text=""
                    inactive-text=""
                  />随机
                </el-col>
              </el-row> -->
              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">图片数量：</div>
                </el-col>
                <el-col :span="8">
                  <el-input-number
                    class="dark"
                    size="small"
                    v-model="obj.imageNum"
                    :min="1"
                  />
                </el-col>
                <!-- <el-col :span="4">
                  <div style="text-align: right">并行：</div>
                </el-col>
                <el-col :span="8">
                  <el-input-number
                    class="dark"
                    size="small"
                    v-model="obj.para"
                    :min="1"
                  />
                </el-col> -->
              </el-row>
<!-- 
              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">模型：</div>
                </el-col>
                <el-col :span="20">
                  <el-select
                    size="small"
                    v-model="obj.moxing"
                    placeholder="Select"
                  >
                    <el-option label="sd-v1-4" value="sd-v1-4" />
                  </el-select>
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">定制VAE：</div>
                </el-col>
                <el-col :span="20">
                  <el-select
                    size="small"
                    v-model="obj.ave"
                    placeholder="Select"
                  >
                    <el-option label="None" value="None" />
                    <el-option
                      label="vae-ft-mse-840000-ema-pruned"
                      value="vae-ft-mse-840000-ema-pruned"
                    />
                  </el-select>
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">采样：</div>
                </el-col>
                <el-col :span="20">
                  <el-select
                    size="small"
                    v-model="obj.caiyang"
                    placeholder="Select"
                  >
                    <el-option label="PLMS" value="PLMS" />
                    <el-option label="DDIM" value="DDIM" />
                    <el-option label="Heun" value="Heun" />
                    <el-option label="Euler" value="Euler" />
                    <el-option
                      label="Euler Ancestral"
                      value="Euler Ancestral"
                    />
                    <el-option label="DPM2" value="DPM2" />
                    <el-option label="DPM2 Ancestral" value="DPM2 Ancestral" />
                    <el-option label="LMS" value="LMS" />
                    <el-option
                      label="DPM Solver (Stability AI)"
                      value="DPM Solver (Stability AI)"
                    />
                    <el-option
                      label="DPM++ 2s Ancestral (Karras)"
                      value="DPM++ 2s Ancestral (Karras)"
                    />
                    <el-option
                      label="DPM++ SDE (Karras)"
                      value="DPM++ SDE (Karras)"
                    />
                    <el-option
                      label="DPM Fast (Karras)"
                      value="DPM Fast (Karras)"
                    />
                    <el-option label="UniPC SNR" value="UniPC SNR" />
                    <el-option label="UniPC TU" value="UniPC TU" />
                    <el-option label="UniPC SNR 2" value="UniPC SNR 2" />
                    <el-option label="UniPC TU 2" value="UniPC TU 2" />
                    <el-option label="UniPC TQ" value="UniPC TQ" />
                  </el-select>
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px" :gutter="3">
                <el-col :span="4">
                  <div style="text-align: right">图片大小：</div>
                </el-col>
                <el-col :span="10">
                  <el-select
                    size="small"
                    v-model="obj.width"
                    placeholder="width"
                    disabled
                  >
                    <el-option
                      :label="item"
                      :value="item"
                      v-for="item in numlist"
                      :key="'l' + item"
                    />
                  </el-select>
                </el-col>
                <el-col :span="10">
                  <el-select
                    size="small"
                    v-model="obj.height"
                    placeholder="height"
                    disabled
                  >
                    <el-option
                      :label="item"
                      :value="item"
                      v-for="item in numlist"
                      :key="'r' + item"
                    />
                  </el-select>
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px" :gutter="3">
                <el-col :span="4">
                  <div style="text-align: right">步骤数：</div>
                </el-col>
                <el-col :span="20">
                  <el-input
                    size="small"
                    v-model="obj.step"
                    style="width: 8em"
                  />
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px" :gutter="3">
                <el-col :span="4">
                  <div style="text-align: right">指导尺度：</div>
                </el-col>
                <el-col :span="20">
                  <input
                    type="range"
                    :value="obj.chidu * 2"
                    @input="rangechidu"
                  />
                  <el-input
                    size="small"
                    v-model="obj.chidu"
                    style="width: 8em"
                  />
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">超网络：</div>
                </el-col>
                <el-col :span="20">
                  <el-select
                    size="small"
                    v-model="obj.chaolianjie"
                    placeholder="Select"
                  >
                    <el-option label="None" value="None" />
                  </el-select>
                </el-col>
              </el-row>
              <el-row style="margin-bottom: 5px">
                <el-col :span="4">
                  <div style="text-align: right">图片格式：</div>
                </el-col>
                <el-col :span="20">
                  <el-select
                    size="small"
                    v-model="obj.imgType"
                    placeholder="Select"
                  >
                    <el-option label=".jpeg" value=".jpeg" />
                    <el-option label=".png" value=".png" />
                    <el-option label=".webp" value=".webp" />
                  </el-select>
                </el-col>
              </el-row>

              <el-row style="margin-bottom: 5px" :gutter="3">
                <el-col :span="4">
                  <div style="text-align: right">图像质量：</div>
                </el-col>
                <el-col :span="20">
                  <input type="range" v-model="obj.zhiliang" />
                  <el-input
                    size="small"
                    v-model="obj.zhiliang"
                    style="width: 8em"
                  />
                </el-col>
              </el-row> -->
            </el-collapse-item>
          </el-collapse>
          <br /> 
          <el-collapse>
            <el-collapse-item name="1">
              <template #title>
                <div class="collapseTitle">
                  <el-icon size="11pt">
                    <Plus />
                  </el-icon>
                  风格配置 (艺术风格、标签等)
                </div>
              </template>
              <el-row>
                <el-col :span="4">图像样式</el-col>
                <el-col :span="8">
                  <el-select
                    v-model="selectType"
                    class="dark"
                    popper-class="dark"
                    size="small"
                    placeholder="Select"
                  >
                    <el-option label="人脸" :value="0" />
                    <el-option label="实景" :value="1" />
                  </el-select>
                </el-col>
              </el-row>
              <el-collapse
                v-model="activeNamesItem"
                v-for="(item, index) in list"
                :key="index"
              >
                <el-collapse-item :name="index">
                  <template #title>
                    <div class="collapseTitle">
                      <el-icon size="11pt">
                        <Plus v-if="activeNamesItem != index" />
                        <Minus v-else />
                      </el-icon>
                      {{ item.category }}
                    </div>
                  </template>
                  <img-com
                    v-for="(v, i) in item.modifiers || []"
                    :key="index + i"
                    :imgUrl="v.previews[selectType].path"
                    :text="v.modifier"
                    :isSelect="!!selectObject[index + '-' + i]"
                    @click="() => selectTypeFunc(v, i, index)"
                  />
                </el-collapse-item>
              </el-collapse>
            </el-collapse-item>
          </el-collapse>
        </div>
      </el-col>
      <el-col :span="16">
        <div class="main right">
          <listItem
            @setconfig="setconfig"
            @removeItem="removeItem"
            @makeimg="makeimg"
            @setImage="setImage"
            :downlist="downlist"
          />
        </div>
      </el-col>
    </el-row>
    <image-edit
      v-if="showImageEdit"
      :file="fileInput"
      @closemain="draw"
      @getimage="getimage"
    />
  </div>
</template>

<script setup>
import imgCom from './components/imgCom.vue';
import imageEle from './components/image.vue';
import imageEdit from './components/imageEdit.vue';
import listItem from './components/listItem.vue';
import { getPaintingStyle, createDraw, queryDraw } from '@/api/index';
import config from '../../config';
import { ref } from 'vue';
const textarea = ref('');
const fileInput = ref({});
const activeNamesItem = ref(-1);
const list = ref([]);
const selectObject = ref({});
const showImageEdit = ref(false);
const selectType = ref(1);
const obj = ref({
  imageNum: 1,
  para: 1,
  zhongzi: '',
  zhongzisuiji: true,
  moxing: 'sd-v1-4',
  ave: 'None',
  caiyang: 'DDIM',
  step: 25,
  chaolianjie: 'None',
  imgType: '.jpeg',
  chidu: 50,
  zhiliang: 75,
  width: 512,
  height: 512,
});
const loading = ref(false);
const ajaxList = [];
const downlist = ref([]);
let l = [];
// const numlist = [
//   128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024,
//   1280, 1536, 1792, 2048,
// ];
document.title = 'AI绘图';
getPaintingStyle({}).then(r => {
  list.value = r || [];
});

const createDr = () => {
  const active_tags = [];
  loading.value = true;
  for (const key in selectObject.value) {
    if (!Object.hasOwnProperty.call(selectObject.value, key)) continue;
    active_tags.push(selectObject.value[key].modifier);
  }
  const f = {
    file: fileInput.value.file,
    fileResult: fileInput.value.fileResult,
  };
  ajaxList.push({
    data: {
      prompt: textarea.value || undefined,
      init_image: f.fileResult,
      active_tags,
    },
    imageNum: obj.value.imageNum || 1,
    status: 0,
  });
  const tags = JSON.parse(JSON.stringify(selectObject.value));
  downlist.value.unshift({
    list: [],
    tags,
    prompt: textarea.value || undefined,
    init_image: f,
    ...obj.value,
    imageNum: obj.value.imageNum || 1,
    status: ajaxList[0].status,
    statusImg: '待定',
  });
  ajax();
};

const ajax = () => {
  if (!ajaxList.length || ajaxList[0].status > ajaxList[0].imageNum) return;
  createDraw({
    data: ajaxList[0].data,
  })
    .then(r => {
      let t = setInterval(() => {
        queryDraw({
          data: r.task,
        }).then(res => {
          downlist.value[0].statusImg = '等待';
          if (res.status !== 'succeeded') return;
          l.push({
            image: res.output[0].data,
            ...res.render_request,
            ...res.task_data,
          });
          ajaxList[0].status += 1;
          downlist.value[0].status = ajaxList[0].status;
          if (ajaxList[0].imageNum - ajaxList[0].status <= 0) {
            ajaxList.shift();
            downlist.value[0].list = l;
            l = [];
            loading.value = false;
            // 当前图已经生成结束
          }
          window.clearInterval(t);
          if (!ajaxList.length) {
            downlist.value[0].statusImg = '';
            return;
          }
          return ajax();
        });
      }, 1000);
    })
    .catch(() => {
      ajaxList[0].status = 0;
    });
};

const selectTypeFunc = (type, i, index) => {
  if (!selectObject.value[index + '-' + i])
    selectObject.value[index + '-' + i] = JSON.parse(JSON.stringify(type));
  else delete selectObject.value[index + '-' + i];
};

const setImage = image => {
    console.log(image)
    fileInput.value.fileResult = image;
    fileInput.value.file = image;
}

const delectSelect = index => {
  delete selectObject.value[index];
};

const selectfile = file => {
  const F = file.target.files[0] || undefined;
  if (!F) {
    closeFunc();
    return;
  }
  var reader = new FileReader();
  reader.readAsDataURL(F); //发起异步请求
  reader.onload = function () {
    //读取完成后，数据保存在对象的result属性中
    file.target.value = '';
    fileInput.value.fileResult = this.result;
    fileInput.value.file = F;
  };
};

const closeFunc = () => {
  fileInput.value.fileResult = undefined;
  fileInput.value.file = undefined;
};

const draw = () => {
  showImageEdit.value = !showImageEdit.value;
};

const removeItem = indexs => {
  const i = indexs.split('-');
  if (i.length === 1 || downlist.value[i[0]].list.length == 1) {
    downlist.value.splice(i[0], 1);
  } else {
    downlist.value[i[0]].list.splice(i[1], 1);
  }
};

const setconfig = item => {
  selectObject.value = item.tags;
  fileInput.value = item.init_image;
  textarea.value = item.prompt || '';
  obj.value.imageNum = item.imageNum || 1;
};

const getimage = base64 => {
  fileInput.value.fileResult = base64;
  fileInput.value.file = base64;
};

// const rangechidu = e => {
//   obj.value.chidu = e.target.value / 2;
// };

const makeimg = item => {
  const active_tags = [];
  loading.value = true;
  for (const key in item.tags || {}) {
    if (!Object.hasOwnProperty.call(item.tags, key)) continue;
    active_tags.push(item.tags[key].modifier);
  }
  const f = {
    file: item.init_image ? item.init_image.file : undefined,
    fileResult: item.init_image ? item.init_image.fileResult : undefined,
  };
  ajaxList.push({
    data: {
      prompt: item.prompt || undefined,
      init_image: f.fileResult,
      active_tags,
    },
    imageNum: item.imageNum || 1,
    status: 0,
  });
  downlist.value.unshift({
    ...item,
    list: [],
    status: ajaxList[0].status,
    statusImg: '待定',
  });
  ajax();
};
</script>

<style scoped>
.diffusion {
  background-color: #202225;
  color: #eee;
  width: 100vw;
  height: 100%;
}

.diffusion > h1 {
  padding: 12px 0;
  font-size: 2em;
}

.body {
  background-color: #36393f;
  width: 100%;
  height: 100%;
  overflow-y: auto;
  padding-bottom: 2em;
}

#logo_img {
  width: 32px;
  height: 32px;
}

.main {
  padding: 0 16px 16px 16px;
}

.label {
  font-size: 10pt;
  font-weight: 700;
  height: 1.5em;
  line-height: 1.5em;
  padding-left: 3px;
  margin-top: 12px;
}

.line {
  margin: 16px 0;
  height: 1px;
  background-color: #202225;
}

.collapseTitle {
  padding-left: 5px;
  font-weight: 700;
  font-size: 11pt;
}

.right {
  padding: 1em;
  width: 100%;
}
</style>

<style>
.diffusion .el-textarea__inner {
  background-color: #202225;
  border: 2px solid #2f3136;
  box-shadow: none;
  color: #fff;
}
.diffusion .el-textarea__inner:focus {
  outline: 2px solid #4d5bff;
}
.diffusion .el-collapse-item__header,
.diffusion .el-collapse,
.diffusion .el-collapse-item__wrap,
.el-popper.is-light,
.el-select__popper.el-popper .el-popper__arrow::before {
  background-color: #2f3136;
  color: #eee;
  border-color: #2f3136;
}
.dark,
.dark * {
  background-color: #202225;
  color: #eee;
  border-color: #2f3136;
}
.dark .el-select-dropdown__item.hover,
.dark .el-select-dropdown__item:hover {
  background-color: #ffffff60;
}
.dark .el-select-dropdown__item.hover span {
  background-color: #ffffff00;
}
.el-popper.is-light,
.el-select__popper.el-popper .el-popper__arrow::before {
  box-shadow: 0 0 5px #ffffff80;
}
.diffusion .el-collapse-item__content {
  color: #eee;
  padding-left: 15px;
}
.diffusion .el-collapse {
  border-radius: 5px;
}

.diffusion .el-input__wrapper {
  box-shadow: 0 0 0 1px #202225 inset;
  background-color: #202225;
}
.diffusion .el-input.is-disabled .el-input__wrapper {
  background-color: #202225;
  box-shadow: 0 0 0 1px #202225 inset;
}
.el-select-dropdown__item.hover {
  background-color: #202225 !important;
}
</style>
