const fileHash = require('../../util/backup_filehash')
const log = require('../../util/log')
const apple_timestamp = require('../../util/apple_timestamp')
const SMS_DB = fileHash('Library/SMS/sms.db')

module.exports = {
  version: 4,
  name: 'messages.messages',
  description: `List all SMS and iMessage messages in a conversation`,
  requiresBackup: true,

  // Run on a v3 lib / backup object.
  run (lib, { backup, id }) {
    return new Promise((resolve, reject) => {
      if (id === undefined) {
        return reject(new Error('You must specify an id for usage with the message report'))
      }

      resolve(getMessages(backup, id))
    })
  },

  // Available fields.
  output: {
    id: el => el.ROWID,
    date: el => el.date,
    sender: el => el.x_sender,
    text: el => (el.text || '').trim(),
    dateRead: el => el.date_read + '',
    dateDelivered: el => el.date_delivered + '',
    isDelivered: el => !!el.is_delivered,
    isFinished: el => !!el.is_finished,
    isFromMe: el => !!el.is_from_me,
    isRead: el => !!el.is_read,
    isSent: el => !!el.is_sent,
    attachments: el => (el.attachments || []).map((at) => at.filename)
  }
}

function getMessages (backup, chatId) {
  return new Promise(async (resolve, reject) => {
    try {
      let messages = await getMessagesiOS10iOS11(backup, chatId)
      resolve(messages)
    } catch (e) {
      log.verbose('iOS 10/11 messages lookup failed', e)
    }

    try {
      let messages = await getMessagesiOS9(backup, chatId)
      resolve(messages)
    } catch (e) {
      log.verbose('iOS 9 messages lookup failed', e)
    }

    reject(new Error('No Suitable messages database or query found. Use -v to see error information'))
  })
}

function getMessagesiOS9 (backup, chatId) {
  return new Promise((resolve, reject) => {
    backup.openDatabase(SMS_DB)
      .then(db => {
        db.all(`
      SELECT 
        message.*,
        handle.id as sender_name,
        ${apple_timestamp.parse(date)} AS date
      FROM chat_message_join 
      INNER JOIN message 
        ON message.rowid = chat_message_join.message_id 
      INNER JOIN handle
        ON handle.rowid = message.handle_id
      WHERE chat_message_join.chat_id = ?`, [parseInt(chatId)],
        async function (err, chats) {
          if (err) return reject(err)

          chats = chats || []

          // Compute the user's name
          for (var i in chats) {
            var el = chats[i]
            el.x_sender = el.is_from_me ? 'Me' : el.sender_name

            // if (!el.is_from_me) {
            //   var contact = await backup.getName(el.sender_name)

            //   if (contact) {
            //     el.x_sender = `${contact.name} <${contact.query}>`
            //   }
            // }
          }

          resolve(chats)
        })
      })
      .catch(reject)
  })
}

function getMessagesiOS10iOS11 (backup, chatId) {
  return new Promise((resolve, reject) => {
    backup.openDatabase(SMS_DB)
      .then(db => {
        db.all(`
      SELECT 
        message.*,
        handle.id as sender_name,
        ${apple_timestamp.parse('date_read')} AS date_read,
        ${apple_timestamp.parse('date_delivered')} AS date_delivered,
        ${apple_timestamp.parse('date')} AS date
      FROM chat_message_join 
      INNER JOIN message 
        ON message.rowid = chat_message_join.message_id 
      INNER JOIN handle
        ON handle.rowid = message.handle_id
      WHERE chat_message_join.chat_id = ?`, [parseInt(chatId)],
        async function (err, chats) {
          if (err) return reject(err)

          chats = chats || []

          // Compute the user's name
          for (var i in chats) {
            var el = chats[i]
            el.x_sender = el.is_from_me ? 'Me' : el.sender_name

            // if (!el.is_from_me) {
            //   var contact = await backup.getName(el.sender_name)

            //   if (contact) {
            //     el.x_sender = `${contact.name} <${contact.query}>`
            //   }
            // }
          }

          resolve(chats)
        })
      })
      .catch(reject)
  })
}