<template>
  <div class="message-dispatcher">
    <div class="g-gutter-sm">
      <q-checkbox v-model="sendInternational" :disable="!editable" :label="`Trimite la numere internaționale (${messages.filter(n => n.destinationType === 'international').length})`" />
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="sendNationalLandline" :disable="!editable" :label="`Trimite la numere naționale fixe (${messages.filter(n => n.destinationType === 'nationalLandline').length})`" />
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="sendNationalMobile" :disable="!editable" :label="`Trimite la numere naționale mobile (${messages.filter(n => n.destinationType === 'nationalMobile').length})`" />
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="resendSuccessfullyDelivered" :disable="!editable" :label="`Retrimite mesaje care au fost livrate cu succes în trecut ${preexistingMessageCounters != null ? '(' + (preexistingMessageCounters['successfully_delivered'] || 0) + ')' : ''}`" />
      <q-spinner-dots color="primary" size="1em" v-if="preexistingMessageStatusesLoading"/>
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="resendSuccessfullySent" :disable="!editable" :label="`Retrimite mesaje care au fost trimise cu succes în trecut ${preexistingMessageCounters != null ? '(' + (preexistingMessageCounters['successfully_sent'] || 0) + ')' : ''}`" />
      <q-spinner-dots color="primary" size="1em" v-if="preexistingMessageStatusesLoading"/>
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="resendUnsuccessfullySent" :disable="!editable" :label="`Retrimite mesaje la care expedierea a eșuat în trecut ${preexistingMessageCounters != null ? '(' + (preexistingMessageCounters['unsuccessfully_sent'] || 0) + ')' : ''}`" />
      <q-spinner-dots color="primary" size="1em" v-if="preexistingMessageStatusesLoading"/>
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="resendUnsent" :disable="!editable" :label="`Retrimite mesaje care sunt deja în coadă ${preexistingMessageCounters != null ? '(' + (preexistingMessageCounters['unsent'] || 0) + ')' : ''}`" />
      <q-spinner-dots color="primary" size="1em" v-if="preexistingMessageStatusesLoading"/>
    </div>
    <div class="g-gutter-sm">
      <q-checkbox v-model="askForDeliveryReport" :disable="!editable" label="Solicită raport de expediere de la rețea (ATENȚIE, ar putea crea probleme în caz de expedieri cu multe mesaje)" />
    </div>
    <div class="g-gutter-sm">
      Pauză între expedieri:
      <q-input
          v-model="pauseBetweenMessagesSeconds"
          type="number"
          filled
          :disable="!editable"
          style="max-width: 125px; display: inline-block;"
          dense
      ></q-input>
      secunde
    </div>
    <device-selector v-model="sender" :stomp-client="stompClient" :connected="connected" :disabled="!editable"></device-selector>
    <div class="g-gutter-sm">
      <q-btn @click="sendMessages" color="primary" icon-right="send" :label="`Expediează ${filteredSelectedMessages.length} SMS-uri`" :disable="!editable || preexistingMessageStatusesLoading || sending || filteredSelectedMessages.length === 0" v-if="filteredSelectedMessages != null"/>
    </div>
    <div class="g-gutter-sm">
      <dispatch-controller :dispatch-uuid="dispatchUuid" :stomp-client="stompClient" :connected="connected" v-if="dispatchUuid != null" @sending-finished="sendingComplete"></dispatch-controller>
    </div>
  </div>
</template>


<script>
module.exports = {
  name: "MessageDispatcher",
  data() {
    return {
      sendInternational: false,
      sendNationalLandline: false,
      sendNationalMobile: true,
      resendSuccessfullySent: false,
      resendSuccessfullyDelivered: false,
      resendUnsuccessfullySent: true,
      resendUnsent: false,
      askForDeliveryReport: false,
      pauseBetweenMessagesSeconds: 0,
      preexistingMessageStatusesLoading: false,
      filteredSelectedMessageContainer: null,
      filteredSelectedMessages: null,
      preexistingMessageCounters: [],
      lastFilteringUpdate: 0,
      sender: "*",
      sending: false,
      dispatchUuid: null,
      stompClient: new ReconnectingStompClient("/wsms", {
        onConnect: () => this.connected = true,
        onDisconnect: () => this.connected = false
      }),
      connected: false
    };
  },
  props: {
    messages: Array,
    editable: Boolean
  },
  computed: {
    selectedMessages() {
      var applicableFilters = [];
      var applicableFilter;
      var messages = this.messages;
      if (!this.sendInternational) {
        applicableFilters.push(message => message.destinationType !== "international");
      }
      if (!this.sendNationalLandline) {
        applicableFilters.push(message => message.destinationType !== "nationalLandline");
      }
      if (!this.sendNationalMobile) {
        applicableFilters.push(message => message.destinationType !== "nationalMobile");
      }
      while ((applicableFilter = applicableFilters.pop()) != null) {
        messages = messages.filter(applicableFilter);
      }
      return messages;
    }
  },
  watch: {
    resendSuccessfullyDelivered: {
      handler() {
        this.lastFilteringUpdate = new Date().getTime();
      }
    },
    resendSuccessfullySent: {
      handler() {
        this.lastFilteringUpdate = new Date().getTime();
      }
    },
    resendUnsuccessfullySent: {
      immediate: true,
      handler() {
        this.lastFilteringUpdate = new Date().getTime();
      }
    },
    resendUnset: {
      immediate: true,
      handler() {
        this.lastFilteringUpdate = new Date().getTime();
      }
    },
    selectedMessages: {
      immediate: true,
      handler() {
        this.lastFilteringUpdate = new Date().getTime();
      }
    },
    lastFilteringUpdate: {
      immediate: true,
      handler() {

        this.preexistingMessageStatusesLoading = true;
        var messageHashes = [];

        this.selectedMessages.forEach(message => {
          messageHashes.push(hash(message));
        });

        axios
            .post('/api/v1/sms/status-by-hash-list', messageHashes)
            .then(response => {
              var statusCounters = {};
              var preexistingMessageStatuses = response.data;
              var statusPredicates = [];
              var messages = this.selectedMessages;
              var filteredMessages = [];
              statusPredicates.push(
                  {
                    name: "successfully_delivered",
                    predicate: preexistingCounts => {
                      return (preexistingCounts["DELIVERED"] || 0) > 0;
                    },
                    target: this.resendSuccessfullyDelivered
                  },
                  {
                    name: "successfully_sent",
                    predicate: preexistingCounts => {
                      return (preexistingCounts["DELIVERED"] || 0) > 0 || (preexistingCounts["DELIVERY_FAILED"] || 0) > 0 || (preexistingCounts["SENT"] || 0) > 0;
                    },
                    target: this.resendSuccessfullySent
                  },
                  {
                    name: "unsuccessfully_sent",
                    predicate: preexistingCounts => {
                      return (preexistingCounts["DELIVERED"] || 0) === 0 && (preexistingCounts["DELIVERY_FAILED"] || 0) === 0 && (preexistingCounts["SENT"] || 0) === 0 && (preexistingCounts["SENDING_FAILED"] || 0) > 0;
                    },
                    target: this.resendUnsuccessfullySent
                  },
                  {
                    name: "unsent",
                    predicate: preexistingCounts => {
                      return (preexistingCounts["DELIVERED"] || 0) === 0 && (preexistingCounts["DELIVERY_FAILED"] || 0) === 0 && (preexistingCounts["SENT"] || 0) === 0 && (preexistingCounts["SENDING_FAILED"] || 0) === 0 && ((preexistingCounts["CREATED"] || 0) > 0 || (preexistingCounts["ALLOCATED"] || 0) > 0 || (preexistingCounts["RESERVED"] || 0));
                    },
                    target: this.resendUnsent
                  }
              );

              messages.forEach(message => {
                var preexistingCounts = preexistingMessageStatuses[hash(message)];
                var passesFilters = true;
                statusPredicates.forEach(filter => {
                  var matches = filter.predicate(preexistingCounts || {});
                  if (matches) {
                    statusCounters[filter.name] = (statusCounters[filter.name] || 0) + 1;
                  }
                  passesFilters &= (!matches || filter.target === matches);
                })
                if (passesFilters) {
                  filteredMessages.push(message);
                }
              });

              this.filteredSelectedMessages = filteredMessages;
              this.preexistingMessageCounters = statusCounters;
              this.preexistingMessageStatusesLoading = false;
            })
            .catch(e => {
              this.filteredSelectedMessages = null;
              this.preexistingMessageCounters = null;
              this.preexistingMessageStatusesLoading = false;
            });

      }
    }
  },
  methods: {
    sendMessages() {
      this.sending = true;
      this.$emit("sending-started");
      var messages = [];

      this.filteredSelectedMessages.forEach(message => {
        messages.push({
          to: message.to,
          content: message.getText()
        });
      });

      var sendOptions = {
        messages: messages,
        resendIdenticalSuccessfullyDeliveredMessages: this.resendSuccessfullyDelivered,
        resendIdenticalSuccessfullySentMessages: this.resendSuccessfullySent,
        resendIdenticalUnsuccessfullySentMessages: this.resendUnsuccessfullySent,
        resendIdenticalUnsent: this.resendUnsent,
        askForDeliveryReport: this.askForDeliveryReport,
        pauseBetweenMessagesSeconds: this.pauseBetweenMessagesSeconds
      };

      if (this.sender !== "*") {
        sendOptions["fromICCID"] = this.sender;
      }

      axios.post('/api/v1/sms/send', sendOptions)
        .then(response => {
          this.dispatchUuid = response.data;
          this.lastFilteringUpdate = new Date();
        })
        .catch(error => {
          var errorMessage;
          try {
            errorMessage = error.response ? JSON.stringify(error.response.data) : error.request ? JSON.stringify(error.request) : error.message;
          } catch (e) {
            errorMessage = error.message;
          }
          this.$q.dialog({
            title: "O eroare s-a produs în timpul expedierii",
            message: errorMessage
          });
          this.sending = false;
          this.lastFilteringUpdate = new Date();
        });
    },
    sendingComplete() {
      this.sending = false;
      this.lastFilteringUpdate = new Date();
      this.$emit("sending-finished");
    }
  },
  beforeDestroy() {
    this.stompClient.disconnect();
  }
}

function hash(message) {
  var md5hash = CryptoJS.algo.MD5.create();
  md5hash.update(message.to);
  md5hash.update(message.getText());
  return md5hash.finalize().toString(CryptoJS.enc.Hex).toUpperCase();
}

</script>

<style scoped>
</style>

<style>
  .row {
    margin: 0 !important;
  }
</style>