const db = require("./model.js"),
  expressLogging = require("express-logging"),
  logger = require("logops")
Entities = require('html-entities').XmlEntities,
  emojiRegex = require('emoji-regex');

const express = require("express");
const bodyParser = require("body-parser");

var app = express();
const entities = new Entities();
const emoRegex = emojiRegex();

app.use(expressLogging(logger));
app.use(
  bodyParser.urlencoded({
    extended: true
  })
);
app.use(bodyParser.json());
app.listen(30300, '127.0.0.1', () => {
  console.log("Server running on port 30300");
});

app.post("/v1/apptype", (req, res, next) => {
  db.AppType.create({
    name: req.body.name,
    description: req.body.description,
    dateCreated: new Date()
  }).then(row => {
    res.json({ code: 200, data: row });
  });
});

app.get("/v1/apptype", (req, res, next) => {
  var clause = { where: { dateDeleted: null } }
  if (req.body.keyword) {
    clause.where.name = { [db.Sequelize.Op.like]: '%' + req.body.keyword + '%' }
  }
  db.AppType.findAll(clause).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.delete("/v1/apptype", (req, res, next) => {
  db.AppType.update({ dateDeleted: new Date() }, { where: { id: { [db.Sequelize.Op.in]: req.body.types } } }).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.put("/v1/apptype", (req, res, next) => {
  console.log(req.body)
  db.AppType.update({
    name: req.body.name,
    description: req.body.description,
    dateUpdated: new Date()
  }, {
      where: { id: req.body.id }
    }).then(rows => {
      res.json({ code: 200, data: rows });
    });
});

app.get("/v1/app", (req, res, next) => {
  var clause = { where: { dateDeleted: null } }
  if (req.body.typeId) {
    clause.where.appType = req.body.typeId
  }
  if (req.body.keyword) {
    clause.where.name = { [db.Sequelize.Op.like]: '%' + req.body.keyword + '%' }
  }
  db.App.findAll(clause).then(apps => {
    res.json({ code: 200, data: apps });
  });
});

app.post("/v1/app", (req, res, next) => {
  db.App.create({
    name: req.body.name,
    appType: req.body.appType,
    status: req.body.status,
    developer: req.body.developer,
    description: req.body.description,
    dateCreated: new Date()
  }).then(row => {
    res.json({ code: 200, data: row });
  });
});

app.put("/v1/app", (req, res, next) => {
  db.App.update({
    name: req.body.name,
    appType: req.body.appType,
    status: req.body.status,
    developer: req.body.developer,
    description: req.body.description,
    dateUpdated: new Date()
  }, {
      where: { id: req.body.id }
    }).then(rows => {
      res.json({ code: 200, data: rows });
    });
});

app.delete("/v1/app", (req, res, next) => {
  db.App.update({ dateDeleted: new Date() }, { where: { id: { [db.Sequelize.Op.in]: req.body.apps } } }).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.get("/v1/category", (req, res, next) => {
  var clause = {}
  if (req.body.id) {
    clause.where = { id: { [db.Sequelize.Op.in]: req.body.id } }
  } else {
    clause.where = { dateDeleted: null, parent: 0 }
    if (req.body.appId) {
      clause.where.app = req.body.appId
    }
    if (req.body.parentId) {
      clause.where.parent = req.body.parentId
    }
    if (req.body.type) {
      clause.where.type = req.body.type
    }
    if (req.body.keyword) {
      clause.where.name = { [db.Sequelize.Op.like]: '%' + req.body.keyword + '%' }
    }

    if (req.body.noparent) {
      delete clause.where.parent;
    }
  }
  db.Category.findAll(clause).then(categories => {
    res.json({ code: 200, data: categories });
  });
});

app.post("/v1/category", (req, res, next) => {
  db.Category.create({
    name: req.body.name,
    app: req.body.app,
    appType: req.body.appType,
    type: req.body.type,
    parent: req.body.parent,
    image: req.body.image,
    subCount: req.body.subCount,
    videoCount: req.body.videoCount,
    dateCreated: new Date()
  }).then(row => {
    db.Category.findOne({ where: { id: req.body.parent } }).then(row => {
      row.subCount++;
      row.save();
    });
    res.json({ code: 200, data: row });
  });
});

app.delete("/v1/category", (req, res, next) => {
  console.log(req.body)
  db.Category.update({ dateDeleted: new Date() }, { where: { id: { [db.Sequelize.Op.in]: req.body.categories } } }).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.put("/v1/category", (req, res, next) => {
  console.log(req.body)
  db.Category.update({
    name: req.body.name,
    app: req.body.app,
    appType: req.body.appType,
    type: req.body.type,
    parent: req.body.parent,
    image: req.body.image,
    subCount: req.body.subCount,
    videoCount: req.body.videoCount,
    dateUpdated: new Date()
  }, {
      where: { id: req.body.id }
    }).then(rows => {
      res.json({ code: 200, data: rows });
    });
});

app.get("/v1/developer", (req, res, next) => {
  var clause = { where: { dateDeleted: null } }
  if (req.body.keyword) {
    clause.where.name = { [db.Sequelize.Op.like]: '%' + req.body.keyword + '%' }
  }
  db.Developer.findAll(clause).then(developers => {
    res.json({ code: 200, data: developers });
  });
});

app.post("/v1/developer", (req, res, next) => {
  db.Developer.create({
    name: req.body.name,
    description: req.body.description,
    dateCreated: new Date()
  }).then(row => {
    res.json({ code: 200, data: row });
  });
});

app.delete("/v1/developer", (req, res, next) => {
  console.log(req.body)
  db.Developer.update({ dateDeleted: new Date() }, { where: { id: { [db.Sequelize.Op.in]: req.body.developers } } }).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.put("/v1/developer", (req, res, next) => {
  console.log(req.body)
  db.Developer.update({
    name: req.body.name,
    description: req.body.description,
    dateUpdated: new Date()
  }, {
      where: { id: req.body.id }
    }).then(rows => {
      res.json({ code: 200, data: rows });
    });
});

app.post("/v1/video", (req, res, next) => {
  console.log(req.body.videos);
  rows = [];
  req.body.videos.map((video, index) => {
    rows.push({
      code: video.id,
      title: video.title,
      description: video.description,
      duration: video.duration,
      dateCreated: new Date(),
      viewCount: video.viewCount,
      likeCount: video.likeCount,
      commentCount: video.commentCount,
      app: video.app,
      category: video.category,
      artist: video.artist
    });
  });

  db.Video.bulkCreate(rows)
    .then(row => {

    })
    .catch(() => {

    });

  db.VideoCategory.bulkCreate(rows, { ignoreDuplicates: true  })
    .then(row => {
      res.json({ code: 200, data: row.length });
    })
    .catch(() => {
      res.json({ code: 500 });
    });
});

app.get("/v1/video", (req, res, next) => {
  Object.assign(req.body, req.query)
  console.log(req.body)
  var clause;
  if (req.body.videos) {
    clause = { where: { code: { [db.Sequelize.Op.in]: req.body.videos } } }
    db.Video.findAll(clause).then(
      videos => {
        res.json({ code: 200, data: videos });
      }
    );
  } else {
    clause = {
      attributes: ['app', 'category', 'id', ['dateCreated', 'vcDateCreated']],
      where: {},
      include: [
        {
          model: db.Video,
          as: 'v',
          where: {}
        },
        {
          model: db.Category,
          as: 'c',
          attributes: ['name']
        },
        {
          model: db.App,
          as: 'a',
          attributes: ['name']
        }
      ]
    }
    if (req.body.appid) {
      clause.where.app = req.body.appid
    }
    if (req.body.category) {
      clause.where.category = req.body.category
    }
    if (req.body.keyword) {
      clause.include[0].where.title = { [db.Sequelize.Op.like]: '%' + req.body.keyword.replace(/[\n\r]+/g, '').replace(' ', '%') + '%' }
    }
    if (req.body.videoCategory) {
      clause.where.id = { [db.Sequelize.Op.in]: req.body.videoCategory }
    }

    if (req.body.sort) {
      if (req.body.sort == 'categoryName') {
        clause.order = db.Sequelize.literal('c.name ' + req.body.order)
      } else if (req.body.sort == 'appname') {
        clause.order = db.Sequelize.literal('a.name ' + req.body.order)
      } else if (req.body.sort == 'title') {
        clause.order = db.Sequelize.literal('v.title ' + req.body.order)
      } else if (req.body.sort == 'code') {
        clause.order = db.Sequelize.literal('v.code ' + req.body.order)
      } else if (req.body.sort == 'duration') {
        clause.order = db.Sequelize.literal('v.duration ' + req.body.order)
      } else if (req.body.sort == 'viewCount') {
        clause.order = db.Sequelize.literal('v.viewCount ' + req.body.order)
      } else if (req.body.sort == 'likeCount') {
        clause.order = db.Sequelize.literal('v.likeCount ' + req.body.order)
      } else if (req.body.sort == 'commentCount') {
        clause.order = db.Sequelize.literal('v.commentCount ' + req.body.order)
      } else if (req.body.sort == 'vcDateCreated') {
        clause.order = db.Sequelize.literal('video_category.dateCreated ' + req.body.order)
      }
    }


    var totalCount = 1;
    clause.attributes.push([db.Sequelize.fn('COUNT', db.Sequelize.col('video_category.id')), 'num'])
    db.VideoCategory.findAll(clause).then(rows => {
      totalCount = JSON.parse(JSON.stringify(rows))[0].num;
      clause.attributes.pop()
      if (req.body.limit) {
        clause.offset = parseInt(req.body.offset)
        clause.limit = parseInt(req.body.limit)
      }
      db.VideoCategory.findAll(clause).then(
        videos => {
          videos.map((video, i) => {
            videos[i].v.title = entities.decode(videos[i].v.title);
            videos[i].v.title = videos[i].v.title.replace(/(\\\u[\{0-9a-f\}]{4,6})+/g, function (match, contents, offset, input_string) {
              var emoji = ''
              var matchSplit = match.split('')
              var i = 0
              while (i < matchSplit.length) {
                emoji = emoji + String.fromCharCode('0x' + matchSplit.slice(i, i + 6).join('').slice(2))
                i = i + 6;
              }
              return emoji;
            }
            )
          })
          res.json({ code: 200, data: videos, total: totalCount });
        }
      );
    })
  }
});

app.delete("/v1/video", (req, res, next) => {
  console.log(req.body)
  db.VideoCategory.destroy({ where: { id: { [db.Sequelize.Op.in]: req.body.videos } } }).then(rows => {
    res.json({ code: 200, data: rows });
  });
});

app.put("/v1/video", (req, res, next) => {
  var video = req.body;
  db.Video.update({
    title: video.title,
    description: video.description,
    duration: video.duration,
    dateUpdated: new Date(),
    viewCount: video.viewCount,
    likeCount: video.likeCount,
    commentCount: video.commentCount,
    app: video.app,
    category: video.category
  }, {
      where: { id: req.body.id }
    }).then(rows => {
      res.json({ code: 200, data: rows });
    });
});

app.post("/v1/video/category", (req, res, next) => {
  var insertRows = []
  req.body.videos.map((video, index) => {
    db.VideoCategory.findAll({ where: { code: video.id, category: video.category } }).then(rows => {
      if (!rows.length) {
        db.VideoCategory.create({
          code: video.id,
          dateCreated: new Date(),
          app: video.app,
          category: video.category
        }).then(row => {
          insertRows.push(row);
        });
      }
    });
  });
  res.json({ code: 200, data: insertRows.length });
});


app.get("/v1/video/category", (req, res, next) => {
  var clause = { where: {} }
  if (req.body.app) {
    clause.where.app = req.body.app
  }
  if (req.body.category) {
    clause.where.category = { [db.Sequelize.Op.like]: req.body.category }
  }
  if (req.body.code) {
    clause.where.code = { [db.Sequelize.Op.like]: req.body.code }
  }
  db.VideoCategory.findAll(clause).then(
    VideoCategory => {
      res.json({ code: 200, data: VideoCategory });
    }
  );
});