const multer = require("multer");
const upload = require("express").Router();
const { exec } = require("child_process");
const { mkdir, readdir, readFile } = require("fs");
const { homedir } = require("os");
const { join } = require("path");
const aws = require("aws-sdk");
const multerS3 = require("multer-s3");
const config = require('./config');
const axios = require('axios');


const spacesEndpoint = new aws.Endpoint("sgp1.digitaloceanspaces.com");
const s3 = new aws.S3({ endpoint: spacesEndpoint });
const temp = `${homedir()}/temp`;

const updateStatus = (urlType,courseId=null, chapterId=null, property,status,roomId=null) =>{
  axios({
    method:'put',
    url:`${config.server}/${urlType}/upload`,
    data:{
      courseId:courseId,
      chapterId:chapterId,
      [property]:status,
      roomId:roomId
    },
    headers:{
      'Authorization':'yezicoco'
    }
  })
  .then((res) => {
    console.log(res.data)
  })
  .catch((err) => {
    console.log(err)
  })
}
const updateDBdata = (urlType,payload) => {
    //params
    //urlType: chapter or curriculum

    axios({
      method:'put',
      url:`${config.server}/${urlType}/upload`,
      data:payload,
      headers:{
        'Authorization':'yezicoco'
      }
    })
    .then((res)=>{
      console.log(res.data)
    })
    .catch((err)=>{
      console.log(err)
    })
}
const queryLastIndex = (urlType, chapterId,property) =>
  new Promise(function(resolve, reject){
        axios({
          method:'get',
          url:`${config.server}/${urlType}/pre/id/${chapterId}`,
          headers:{
            'Authorization':'yezicoco'
          }
        })
        .then((res)=>{
          resolve(res.data[property].length)
        })
        .catch((err)=>{
          console.log(err)
        })
  })

const queryLatestData = (urlType, chapterId, property) =>
  new Promise ((resolve, reject) => {
    axios({
      method:'get',
      url:`${config.server}/${urlType}/pre/id/${chapterId}`,
      headers:{
        'Authorization':'yezicoco'
      }
    })
    .then((res)=>{
      resolve(res.data[property])
    })
    .catch((err)=>{
      console.log(err)
    })
  })



const generatorMultipleArray = (courseId, chapterId, type,length,format='',filename='') =>{
  let arr = [];
  let baseUrl = `https://ccrb-cs.sgp1.digitaloceanspaces.com/course/${courseId}/${type}/${chapterId}/${chapterId}_`
  for(let index = 1 ; index <= length;index++){
    arr.push(baseUrl+index+'.'+format + filename);
  }
  return arr;
};
const generatorRoomMultipleArray = (roomId, type,length,format='',filename='') =>{
  let arr = [];
  let baseUrl = `https://ccrb-cs.sgp1.digitaloceanspaces.com/room/${roomId}/${type}/${roomId}_`
  for(let index = 1 ; index <= length;index++){
    arr.push(baseUrl+index+'.'+format + filename);
  }
  return arr;
};

const uploadAttachment2space = () => multer({
  storage: multerS3({
    s3: s3,
    bucket: (req, file, cb) => {
      cb(null, `ccrb-cs/course/${req.body.courseId}/attachments/${req.body.chapterId}`);
    },
    acl: "public-read",
    key: function(req, file, cb) {
      cb(null,file.originalname);
    }
  })
});


const uploadFile2Space = (type,category) =>{
  if(category === 'course'){
    return (course, bucket='', dir, file) => new Promise((resovle, reject) => {
      const params = {
        Bucket: `ccrb-cs/course/${course}/${type}${bucket?'/':''}${bucket}`,
        Key: `${file}`,
        ACL: "public-read"
      };
      readFile(`${dir}/${file}`, (err, buf) => {
        if (err)
          return console.error(err);
        params.Body = buf;
        s3.putObject(params, (err,data) => {
          if (err) {
            console.error(err);
            return reject(err);
          }else{
            let response = {
              status:200,
              url:`${config.space}/course/${course}/${type}${bucket?'/':''}${bucket}/${file}`,
            }
            return resovle(response);
          }
        });
      });
    })
  }else if(category === 'room'){
    return (roomId, bucket='', dir, file) => new Promise((resovle, reject) => {
      const params = {
        Bucket: `ccrb-cs/room/${roomId}/${type}${bucket?'/':''}${bucket}`,
        Key: `${file}`,
        ACL: "public-read"
      };
      readFile(`${dir}/${file}`, (err, buf) => {
        if (err)
          return console.error(err);
        params.Body = buf;
        s3.putObject(params, (err,data) => {
          if (err) {
            console.error(err);
            return reject(err);
          }else{
            let response = {
              status:200,
              url:`${config.space}/room/${roomId}/${type}${bucket?'/':''}${bucket}/${file}`,
            }
            return resovle(response);
          }
        });
      });
    })
  }
};

//course
const slide2SpacePromise = uploadFile2Space('slides','course');
const clip2SpacePromise = uploadFile2Space('clips','course');
const thumb2SpacePromise = uploadFile2Space('thumbs','course');
const cover2SpacePromise = uploadFile2Space('covers','course');
const demo2SpacePromise = uploadFile2Space('demos','course');
//pdf
const roomSlide2SpacePromise = uploadFile2Space('slides','room');


const uploadPdf2Server = () => multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      const filename = req.body.roomId? req.body.roomId:req.body.chapterId;
      const dir = `${temp}/pdf/${filename}`;
      mkdir(dir, { recursive: true }, () => cb(null, dir));
    },
    filename: (req, file, cb) => {
      const filename = req.body.roomId? req.body.roomId:req.body.chapterId;
      return cb(null, `${filename}.pdf`)
    }
  })
});

const runBash = command => new Promise((resovle, reject) => {
  exec(command, (err,stdout, stderr) => err? reject(err): resovle(stdout));
});

const uploadJpg2Space = (courseId, chapterId, dir, files, index,bashmsg,category) =>
  {if(category === 'course'){
    slide2SpacePromise(courseId, chapterId, dir, files[index])
      .then((res) => {
        delete files[index];
        if (Object.keys(files).length === 0) {
          console.log(bashmsg);
          let pages = bashmsg.slice(bashmsg.indexOf('Total pages: ')+13);
          let slides = generatorMultipleArray(courseId, chapterId, 'slides', pages, 'jpg');
          updateDBdata('chapter',{courseId:courseId,chapterId:chapterId,slideUrl:slides})
          exec(`rm -rf ${dir}`, err => err? console.error(err): '');
        }
      })
      .catch(err => {
        // catch the error from uploading jpg file to spaces
        console.error(err);
        uploadJpg2Space(courseId, chapterId, dir, files, index);
      });
  }else if(category === 'room'){
    roomSlide2SpacePromise(courseId, chapterId, dir, files[index])
      .then((res) => {
        delete files[index];
        if (Object.keys(files).length === 0) {
          console.log(bashmsg);
          let pages = bashmsg.slice(bashmsg.indexOf('Total pages: ')+13);
          let slides = generatorRoomMultipleArray(courseId,'slides', pages, 'jpg');
          updateDBdata('room',{roomId:courseId,slideUrl:slides})
          exec(`rm -rf ${dir}`, err => err? console.error(err): '');
        }
      })
      .catch(err => {
        // catch the error from uploading jpg file to spaces
        console.error(err);
        uploadJpg2Space(courseId, chapterId, dir, files, index);
      });
  }
}

upload.post("/pdf", (req, res) => {
  uploadPdf2Server().single("pdf")(req, res, err => {
    if (err) {
      console.error(err);
      return res.status(401).send("upload pdf failed");
    }
    const { courseId, chapterId ,roomId} = req.body;

    if(req.body.courseId && req.body.chapterId){
      const raw = `${temp}/pdf/${chapterId}`;
      const slide = `${raw}/slides`;
      //Update status before run bash
      //to declare property is not empty
      updateStatus('chapter',courseId, chapterId, 'slideUrl','pending');

      runBash(`./pdf2jpg.bash ${raw} ${chapterId}`)
        .then((res) => {
          readdir(slide, (err, files) => {
            if (err)
              return console.error(err);
            const filesTree = {};
            files.forEach((file, i) => (filesTree[i] = file));
            files.forEach((file, i) => {
              let bash = {
                message:res
              }
              uploadJpg2Space(courseId, chapterId, slide, filesTree, i, bash.message,'course');
            });
          });
        })
        .catch(err => console.error(err));
      res.send("OK");
    }else if (req.body.roomId) {
      const raw = `${temp}/pdf/${roomId}`;
      const slide = `${raw}/slides`;
      //Update status before run bash
      //to declare property is not empty
      updateStatus('room',null,null, 'slideUrl','pending',req.body.roomId);

      runBash(`./pdf2jpg.bash ${raw} ${roomId}`)
        .then((res) => {
          readdir(slide, (err, files) => {
            if (err)
              return console.error(err);
            const filesTree = {};
            files.forEach((file, i) => (filesTree[i] = file));
            files.forEach((file, i) => {
              let bash = {
                message:res
              }
              uploadJpg2Space(roomId, chapterId, slide, filesTree, i, bash.message,'room');
            });
          });
        })
        .catch(err => console.error(err));
      res.send("OK");
    }else{
      res.status(422).send('INVALID PAYLOAD');
    }
  });
});


const uploadClip2Server = () => multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      const dir = `${temp}/raw-clips/`;
      mkdir(dir, { recursive: true }, () => cb(null, dir));
    },
    filename: (req, file, cb) => {
      const suffix = file.originalname.match(/\.[\w]+$/);
      cb(null, `${req.body.uuid}${suffix ? suffix[0] : ""}`);
    }
  })
});

const uploadClip2Space = (courseId, chapterId, dir, filename) =>
  clip2SpacePromise(courseId, chapterId, dir, filename)
    .then((res) =>{
      if(res.status === 200){
        exec(`rm ${dir}/${filename}`,err => err? console.error(err): '');

        queryLastIndex('chapter',chapterId,'clipUrl')
          .then((lastIndex)=>{
            console.log(lastIndex);
            let clipUrl = generatorMultipleArray(courseId, chapterId, 'clips', lastIndex+1, 'mp4');
            let thumbUrl = generatorMultipleArray(courseId, chapterId, 'thumbs', lastIndex+1, 'jpg');
            updateDBdata('chapter',{chapterId:chapterId, clipUrl:clipUrl})
            updateDBdata('chapter',{chapterId:chapterId, thumbUrl:thumbUrl})
          })
          .catch((err)=>{console.log(err)});
        // updateDBdata('curriculum',{courseId:courseId,demo:res.url})
      }else{
        console.log('Upload clips Something Wrong.')
      }
    })
    .catch(err => {
      // catch the error from uploading jpg file to spaces
      console.error(err);
      uploadClip2Space(courseId, chapterId, dir, filename);
    });

const uploadThumb2Space = (courseId, chapterId, dir, filename) =>
  thumb2SpacePromise(courseId, chapterId, dir, filename)
    .then(() => exec(`rm ${dir}/${filename}`,
      err => err? console.error(err): ''))
    .catch(err => {
      // catch the error from uploading jpg file to spaces
      console.error(err);
      uploadThumb2Space(courseId, chapterId, dir, filename);
    });

upload.post("/clip", (req, res) => {
  uploadClip2Server().single("clip")(req, res, err => {
    if (err) {
      console.error(err);
      return res.status(401).send("upload clip failed");
    }
    const { courseId, chapterId, uuid } = req.body;
    const { filename } = req.file;
    const raw = `${temp}/raw-clips/${filename}`;
    runBash(`./videoProcess.bash ${raw} ${temp}`)
      .then(() => {
        exec(`rm ${raw}`, err => err? console.error(err): '');
        uploadClip2Space(courseId, chapterId, `${temp}/clips`, `${uuid}.mp4`);
        uploadThumb2Space(courseId, chapterId, `${temp}/thumbs`, `${uuid}.jpg`);
      })
      .catch(err => console.error(err))
    return res.send("upload clip successfully");
  });
});


upload.post("/attach", (req, res) => {
  uploadAttachment2space().single("attachment")(req, res, err => {
    if (err) {
      console.error(err);
      return res.status(401).send("upload attachment failed");
    }else{
      let {courseId, chapterId } = req.body;
      const { originalname } = req.file;
      queryLatestData('chapter',chapterId,'attachmentUrl')
        .then((latestData) => {
          let baseUrl = `https://ccrb-cs.sgp1.digitaloceanspaces.com/course/${courseId}/attachments/${chapterId}/${originalname}`
          let attachmentUrl = latestData;
          attachmentUrl.push(baseUrl);
          updateDBdata('chapter',{courseId:courseId,chapterId:chapterId,attachmentUrl:attachmentUrl})
          res.send("upload attachment successfully");
        })
        .catch(err=>{
          console.log(err);
        })

    }

  });
});


const uploadCover2Server = () => multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      const dir = `${temp}/raw-covers`;
      mkdir(dir, { recursive: true }, () => cb(null, dir));
    },
    filename: (req, file, cb) => {
      const suffix = file.originalname.match(/\.[\w]+$/);
      cb(null, `${req.body.name}${suffix? suffix[0]: ''}`);
    }
  })
});

const uploadCover2Space = (courseId, dir, filename,chapterId) =>
  cover2SpacePromise(courseId, '', dir, filename)
    .then((res) =>{
      if(res.status === 200){
        exec(`rm ${dir}/${filename}`,err => err? console.error(err): '')
        //Due to upload cover use same route path
        //verify chapterId is exist
        if(chapterId){
          updateDBdata('chapter',{courseId:courseId,chapterId:chapterId,bg:res.url})
        }else{
          updateDBdata('curriculum',{courseId:courseId,poster:res.url})
        }
      }else{
        console.log('Something Wrong.')
      }
    })
    .catch(err => {
      // catch the error from uploading jpg file to spaces
      console.error(err);
      uploadCover2Space(courseId, dir, filename);
    });

upload.post("/cover", (req, res) => {
  uploadCover2Server().single("cover")(req, res, err => {
    if (err) {
      console.error(err);
      return res.status(401).send("upload cover failed");
    }
    const { courseId, name , chapterId } = req.body;
    const { filename } = req.file;
    const raw = `${temp}/raw-covers/${filename}`;
    const cover = `${temp}/covers`
    runBash(`./coverResize.bash ${raw} ${cover}/${name}`)
      .then(() => {
        exec(`rm ${raw}`, err => err? console.error(err): '');
        uploadCover2Space(courseId, cover, `${name}.jpg`,chapterId||null);
      })
      .catch(err => console.error(err));
    return res.send("upload cover successfully");
  });
});


const uploadDemo2Server = () => multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      const dir = `${temp}/raw-demos`;
      mkdir(dir, { recursive: true }, () => cb(null, dir));
    },
    filename: (req, file, cb) => {
      const suffix = file.originalname.match(/\.[\w]+$/);
      cb(null, `${req.body.courseId}${suffix? suffix[0]: ''}`);
    }
  })
});

const uploadDemo2Space = (courseId, dir, filename) =>
  demo2SpacePromise(courseId, '', dir, filename)
    .then((res) =>{
      if(res.status === 200){
        exec(`rm ${dir}/${filename}`,err => err? console.error(err): '')
        updateDBdata('curriculum',{courseId:courseId,demo:res.url})
      }else{
        console.log('Upload demo Something Wrong.')
      }
    })
    .catch(err => {
      // catch the error from uploading jpg file to spaces
      console.error(err);
      uploadDemo2Space(courseId, dir, filename);
    });

upload.post("/demo", (req, res) => {
  uploadDemo2Server().single('demo')(req, res, err => {
    if (err) {
      console.error(err);
      return res.status(401).send("upload demo failed");
    }
    const { courseId } = req.body;
    const { filename } = req.file;
    const raw = `${temp}/raw-demos/${filename}`;
    const type = req.file.mimetype.split('/')[0];
    let bash = '';
    if (type === 'image') {
      bash = './demoImageResize.bash';
    } else if (type === 'video') {
      bash = './demoVideoResize.bash';
    } else {
      return res.status(401).send("wrong file type");
    }
    runBash(`${bash} ${raw} ${temp}/demos/${courseId}`)
      .then(() => {
        exec(`rm ${raw}`, err => err? console.error(err): '');
        const suffix = type === 'image'? '.jpg': '.mp4';
        uploadDemo2Space(courseId, `${temp}/demos`, `${courseId}${suffix}`);
      })
      .catch(err => console.error(err));
    return res.send("upload demo successfully");
  });
})




// ---------------------------------------------------------------------------- //

const photoDirPath = join(__dirname, "static", "images", "workshop", "3");
const imageStorage = multer.diskStorage({
  destination: photoDirPath,
  filename: (req, file, cb) => {
    const { username } = req.body;
    const types = file.mimetype.split("/");
    if (types[0] === "image") {
      cb(
        null,
        (username ? username : "Untitled") + `-${Date.now()}.${types[1]}`
      );
    }
  }
});
const singleImageStore = multer({ storage: imageStorage }).single("userphoto");

upload.get("/all_photos", (req, res) => {
  readdir(photoDirPath, (err, files) => {
    if (err) return res.json({ message: "error", error: err });
    else return res.json({ message: "ok", files: files });
  });
});

upload.post("/images", singleImageStore, (req, res) => {
  console.log("save photo");
  res.json({ msg: "Upload photo successfully" });
});

module.exports = upload;
