import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
const gcs = require('@google-cloud/storage')();
const spawn = require('child-process-promise').spawn;
const path = require('path');
const os = require('os');
const fs = require('fs');
admin.initializeApp(functions.config().firebase);

type Message = {
  timestamp: number;
  authorId: string;
  authorName: string;
  recipientId: string;
  body: string
  toMuted: boolean;
};

enum ApplicationStatus {
  PENDING = 'pending',
  ACCEPTED = 'accepted',
  REJECTED = 'rejected',
}
type Application = {
  id: string;
  offerId: string;
  offerName: string;
  employerId: string;
  employeeId: string;
  employeeDisplayName: string;
  status: ApplicationStatus;
};

exports.generateThumbnail = functions.storage.object().onChange((event) => {
  const object = event.data; // The Storage object.
  const fileBucket = object.bucket; // The Storage bucket that contains the file.
  const filePath = object.name; // File path in the bucket.
  const contentType = object.contentType; // File content type.
  const resourceState = object.resourceState; // The resourceState is 'exists' or 'not_exists' (for file/folder deletions).
  const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.
  // Exit if this is triggered on a file that is not an image.
  if (!contentType.startsWith('image/')) {
    return null;
  }

  // Get the file name.
  const fileName = path.basename(filePath);
  // Exit if the image is already a thumbnail.
  if (fileName.startsWith('thumb_')) {
    return null;
  }

  // Exit if this is a move or deletion event.
  if (resourceState === 'not_exists') {
    return null;
  }

  // Exit if file exists but is not new and is only being triggered
  // because of a metadata change.
  if (resourceState === 'exists' && metageneration > 1) {
    return null;
  }
  const bucket = gcs.bucket(fileBucket);
  const tempFilePath = path.join(os.tmpdir(), fileName);
  const metadata = {
    contentType: contentType,
  };
  return bucket.file(filePath).download({
    destination: tempFilePath,
  }).then(() => {
    // Generate a thumbnail using ImageMagick.
    return spawn('convert', [tempFilePath, '-thumbnail', '500x500>', tempFilePath]);
  }).then(() => {
    // We add a 'thumb_' prefix to thumbnails file name. That's where we'll upload the thumbnail.
    const thumbFileName = `thumb_${fileName}`;
    const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
    // Uploading the thumbnail.
    return bucket.upload(tempFilePath, {
      destination: thumbFilePath,
      metadata: metadata,
    });
    // Once the thumbnail has been uploaded delete the local file to free up disk space.
  }).then((file) => {
    fs.unlinkSync(tempFilePath);
    file.makePublic();
    bucket.file(filePath).delete()
      .catch((error) => console.error(error));
  });
});

exports.sendPushForApplicationStatus = functions.firestore.document('env/{env}/applications/{applicationId}')
  .onUpdate((event) => {
    const previous = event.data.previous.data() as Application;
    const current = event.data.data() as Application;
    if (current.status !== previous.status) {
      const payload = {
        notification: {
          title: current.offerName,
          body: `Aplikacja została ${current.status === ApplicationStatus.ACCEPTED ? 'zaakceptowana' : 'odrzucona'}`,
          sound: 'default',
        },
        data: {
          offerId: current.offerId,
          status: current.status,
        }
      }
      const recipientId = current.employeeId;
      if (recipientId) {
        return admin.firestore()
          .doc(`env/${event.params.env}/users/${recipientId}`)
          .get()
          .then((doc) => {
            const pushToken = doc.data().pushToken;
            if (pushToken) {
              return admin.messaging().sendToDevice(pushToken, payload);
            }
            return null;
          });
      }
    }
    return null;
  });

exports.sendPushForMessage = functions.firestore.document('env/{env}/conversations/{conversationId}/messages/{messageId}')
  .onCreate((event) => {
    const MSG_LENGHT_LIMIT = 150
    const message = event.data.data() as Message;
    if (message.toMuted) {
      return null;
    }
    const body = message.body.length > MSG_LENGHT_LIMIT
      ? message.body.substr(0, 150).concat('...')
      : message.body;
    const payload = {
      notification: {
        title: message.authorName,
        body,
        sound: 'default',
        tag: event.params.conversationId,
      },
      data: {
        conversationId: event.params.conversationId,
      }
    }
    const recipientId = message.recipientId;
    if (recipientId) {
      return admin.firestore()
        .doc(`env/${event.params.env}/users/${recipientId}`)
        .get()
        .then((doc) => {
          const pushToken = doc.data().pushToken;
          if (pushToken) {
            return admin.messaging().sendToDevice(pushToken, payload);
          }
          return null;
        });
    } else {
      return null;
    }
  });
