<html>
<!-- Empty head might be needed for setSenderImage -->
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta charset=“utf-8”>
</head>

<body>
  <div id="invitation">
    <div id="text">
    </div>
    <div id="actions">
      <div id="accept-btn" class="invitation-button button-green" onclick="acceptInvitation()" >Accept</div>
      <div id="refuse-btn" class="invitation-button button-red" onclick="refuseInvitation()" >Refuse</div>
      <div id="block-btn" class="invitation-button button-red" onclick="blockConversation()" >Block</div>
    </div>
  </div>
    <div id="container">
      <div id="messages"></div>

      <div id="sendMessage">
        <textarea id="message" autofocus placeholder="Type a message" onkeyup="grow_text_area()" rows="1" disabled="false"></textarea>
        <div class="msg-button" onclick="sendMessage()" title="Send">
          <svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
              <path xmlns="http://www.w3.org/2000/svg" d="M12,11.874v4.357l7-6.69l-7-6.572v3.983c-8.775,0-11,9.732-11,9.732C3.484,12.296,7.237,11.874,12,11.874z"/>
          </svg>
        </div>
        <div class="msg-button" onclick="sendFile()" title="Send File">
          <svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
              <path d="M0 0h24v24H0z" fill="none" />
              <path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
          </svg>
        </div>
      </div>
      </form>
    </div>
</body>

<script>

const avatar_size = 35;
var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
var displayLinksEnabled = false;
var historyBufferIndex = 0; // When showing a large amount of interactions, this counter store the interaction's index to show
var historyBuffer = []; // Before showing a large amount of interactions, this array is used as a buffer.
var hoverBackButtonAllowed = true;

/* We retrieve refs to the most used navbar and message bar elements for efficiency purposes */
/* NOTE: always use getElementById when possible, way more efficient */
const messageBar        = document.getElementById('sendMessage');
const messageBarInput   = document.getElementById("message");
const messages          = document.getElementById("messages");
const invitation        = document.getElementById("invitation");
const invitationText    = document.getElementById('text');

/* States: allows us to avoid re-doing something if it isn't meaningful */
var hasInvitation = false;

messageBarInput.addEventListener("keydown", function (e) {
    e = e || event;
    var map = {};
    map[e.keyCode] = e.type == 'keydown';
    if (e.ctrlKey || e.shiftKey) {
      return true;
    }
    if (map[13]) {
      sendMessage();
      e.preventDefault();
    }
    return true;
});

function grow_text_area() {
    var is_at_bottom = messages.scrollTop === (messages.scrollHeight - messages.offsetHeight);

    var old_height = messageBarInput.style.height;
    messageBarInput.style.height = "auto";
    messageBarInput.style.height = messageBarInput.scrollHeight +"px";

    if (is_at_bottom) {
      messages.scrollTop = messages.scrollHeight;
    }
}

/*
 * Update timestamps messages
 */
function updateView() {
    updateTimestamps();
}

setInterval(updateView, 60000);

window.onresize = function(event) {
    updateTimestamps();
};

function setDisplayLinks(display) {
  displayLinksEnabled = display;
}

/**
 * Transform a date to a string group like "1 hour ago".
 */
function formatDate(date) {
    const seconds = Math.floor((new Date() - date) / 1000);
    var interval = Math.floor(seconds / (3600 * 24));
    if (interval > 5) {
        return date.toLocaleDateString();
    }
    if (interval > 1) {
        return interval + ' days ago';
    }
    if (interval === 1) {
        return interval + ' day ago';
    }
    interval = Math.floor(seconds / 3600);
    if (interval > 1) {
        return interval + ' hours ago';
    }
    if (interval === 1) {
        return interval + ' hour ago';
    }
    interval = Math.floor(seconds / 60);
    if (interval > 1) {
        return interval + ' minutes ago';
    }
    return 'just now';
}

/**
 * Send #sendMessage #message value
 */
 function sendMessage()
 {
     var message = messageBarInput.value;
     if (message.length > 0) {
         messageBarInput.value = '';
         window.prompt('SEND:' + message);
     }
 }

/**
* Disable or enable textarea
*/
function disableSendMessage(isDisabled)
{
    messageBarInput.disabled = isDisabled;
}

/**
 * Change the value of the progress bar
 */
function hideMessageBar(isHidden) {
    isHidden ? messageBar.classList.add("hiddenState") : messageBar.classList.remove("hiddenState");
}

/**
 * Accept an invite
 */
function acceptInvitation()
{
    window.prompt('ACCEPT');
}

/**
 * Refuse an invite
 */
function refuseInvitation()
{
    window.prompt('REFUSE');
}

/**
 * Accept an invite
 */
function blockConversation()
{
    window.prompt('BLOCK');
}

/**
 * Change the content of the div invitation and show it
 * @param  contactAlias
 */
function showInvitation(contactAlias) {
  hasInvitation = true;
  invitationText.innerHTML = '<h1>' + contactAlias + ' sends you an invitation</h1>'
  + 'Do you want to add them to the conversations list?<br>'
  + 'Note: you can automatically accept this invitation by sending a message.';
  invitation.style.visibility = 'visible';
}

/**
 * Hide the content of invitation
 */
function hideInvitation() {
  if (hasInvitation) {
      hasInvitation = false;
      invitation.style.visibility = 'hidden';
  }
}

/**
 * Clears all messages
 */
function clearMessages()
{
    messages.innerHTML = "";
}

/**
 * Converts text to HTML
 */
function escapeHtml(html)
{
    var text = document.createTextNode(html);
    var div = document.createElement('div');
    div.appendChild(text);
    return div.innerHTML;
}


/**
 * Get the youtube video id from a URI
 */
function youtube_id(url) {
    const regExp = /^.*(youtu\.be\/|v\/|\/u\/w|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
    const match = url.match(regExp);
    return (match && match[2].length == 11) ? match[2] : null;
}

/**
 * Returns HTML message from the message text.
 * Cleaned and linkified.
 */
function getMessageHtml(message_text)
{
  const escaped_message = escapeHtml(message_text);
  var linkified_message = linkifyHtml(escaped_message, {});

  const textPart = document.createElement('pre');
  textPart.innerHTML = linkified_message;

  return textPart.outerHTML;
}

/**
 * Returns the message status, formatted for display
 */
function getMessageDeliveryStatusText(message_delivery_status)
{
    var formatted_delivery_status = message_delivery_status;

    switch(message_delivery_status)
    {
        case "sending":
        case "ongoing":
            formatted_delivery_status = "Sending<svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><circle class='status_circle anim-first' cx='4' cy='12' r='1'/><circle class='status_circle anim-second' cx='8' cy='12' r='1'/><circle class='status_circle anim-third' cx='12' cy='12' r='1'/></svg>";
            break;
        case "failure":
            formatted_delivery_status = "Failure <svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><path class='status-x x-first' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M4,4 L12,12'/><path class='status-x x-second' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M12,4 L4,12'/></svg>";
            break;
        case "sent":
        case "finished":
        case "unknown":
        case "read":
            formatted_delivery_status = "";
            break;
        default:
            console.log("getMessageDeliveryStatusText: unknown delivery status: " + message_delivery_status);
            break;
    }

    return formatted_delivery_status;
}

/**
 * Returns the message date, formatted for display
 */
function getMessageTimestampText(message_timestamp, custom_format)
{
  const date = new Date(1000 * message_timestamp);
  if(custom_format) {
      return formatDate(date);
  } else {
      return date.toLocaleString();
  }
}

/**
 * Merge timestamps if they are from the same group (likes: "1 hour ago")
 */
function cleanPreviousTimestamps (baseNode, endIndex) {
    // Remove previous elements with the same formatted timestamp
    for (var c = endIndex - 1 ; c >= 0 ; --c) {
        const child = messages.children[c];
        if (child.className.indexOf('timestamp') !== -1) {
            if (child.className === baseNode.className &&
            child.innerHTML === baseNode.innerHTML) {
                messages.removeChild(child);
            } else {
                break; // A different timestamp is met, we can stop here.
            }
        }
    }
}

/**
 * Update timestamps
 */
function updateTimestamps() {
    const timestamps = messages.querySelectorAll('.timestamp');
    const is_image_out = messages.querySelector('.message_out .sender_image')
    const is_image_in = messages.querySelector('.message_in .sender_image')
    if (timestamps) {
        for ( var c = 0 ; c < messages.children.length ; ++c) {
          const child = messages.children[c];
          if (child.className.indexOf('timestamp') !== -1) {
                // Update timestamp
                child.innerHTML = getMessageTimestampText(child.getAttribute('message_timestamp'), true)

                var desktop_margin = '25%'
                const height = document.body.clientHeight
                const width = document.body.clientWidth
                if (width <= 1920 || height <= 1080) {
                  desktop_margin = '15%'
                }
                if (width <= 1000 || height <= 480) {
                  desktop_margin = '0px'
                }
                if (child.className.indexOf('timestamp_out') !== -1) {
                  const avatar_px = is_image_out ? (is_image_out.offsetHeight === avatar_size ? '60px' : '20px') : '20px'
                  child.style.paddingRight = `calc(${desktop_margin} + ${avatar_px})`
                } else if (child.className.indexOf('timestamp_in') !== -1) {
                  const avatar_px = is_image_in ? (is_image_in.offsetHeight === avatar_size ? '60px' : '20px') : '20px'
                  child.style.paddingLeft = `calc(${desktop_margin} + ${avatar_px})`
                }
                // Remove previous elements with the same formatted timestamp
                cleanPreviousTimestamps(child, c);
            }
        }
    }
}

/**
 * Convert a value in filesize
 */
 function humanFileSize(bytes) {
    var thresh = 1024;
    if(Math.abs(bytes) < thresh) {
        return bytes + ' B';
    }
    var units = ['kB','MB','GB','TB','PB','EB','ZB','YB']
    var u = -1;
    do {
        bytes /= thresh;
        ++u;
    } while(Math.abs(bytes) >= thresh && u < units.length - 1);
    return bytes.toFixed(1)+' '+units[u];
}

/**
 * Change the value of the progress bar
 */
function updateProgressBar(progress_bar, message_object, message_delivery_status) {
  var delivery_status = message_object["delivery_status"];
  if ("progress" in message_object && !isErrorStatus(delivery_status) && message_object["progress"] !== 100) {
    var progress_percent = (100 * message_object["progress"] / message_object["totalSize"]);
    if (progress_percent !== 100)
      progress_bar.childNodes[0].setAttribute("style", "width: " + progress_percent + "%");
    else
      progress_bar.setAttribute("style", "display: none");
  } else
    progress_bar.setAttribute("style", "display: none");
}

/**
 * Check if a status is an error status
 */
function isErrorStatus(status) {
  return (status === 'failure'
         || status === 'awaiting peer timeout'
         || status === 'canceled'
         || status === 'unjoinable peer');
}

/**
 * Build a new file interaction
 * @param message_id
 */
function fileInteraction(message_id) {
  var message_wrapper = document.createElement('div')
  message_wrapper.setAttribute('class', 'message_wrapper')

  // An file interaction contains buttons at the left of the interaction
  // for the status or accept/refuse
  var left_buttons = document.createElement('div')
  left_buttons.setAttribute('class', 'left_buttons')
  message_wrapper.appendChild(left_buttons)
  // Also contains a bold clickable text
  var text_div = document.createElement('div')
  text_div.setAttribute('class', 'text')
  text_div.addEventListener('click', function (event) {
    // ask ring to open the file
    const filename = document.querySelector('#message_' + message_id + ' .full').innerText
    window.prompt('OPEN_FILE:' + filename)
  });
  var full_div = document.createElement('div')
  full_div.setAttribute('class', 'full')
  full_div.style = 'visibility: hidden; display: none;'
  var message_text = document.createElement('div')
  message_text.setAttribute('class', 'filename')
  // And some informations like size or error message.
  var informations_div = document.createElement('div')
  informations_div.setAttribute('class', 'informations')
  text_div.appendChild(message_text)
  text_div.appendChild(full_div)
  text_div.appendChild(informations_div)
  message_wrapper.appendChild(text_div)
  // And finally, a progress bar
  message_transfer_progress_bar = document.createElement('span')
  message_transfer_progress_bar.setAttribute('class', 'message_progress_bar')
  message_transfer_progress_completion = document.createElement('span')
  message_transfer_progress_bar.appendChild(message_transfer_progress_completion)
  message_wrapper.appendChild(message_transfer_progress_bar)
  return message_wrapper
}

/**
 * Update a file interaction (icons + filename + status + progress bar)
 * @param message_div the message to update
 * @param message_object new informations
 */
 function updateFileInteraction(message_div, message_object, forceTypeToFile = false) {
   if (!message_div.querySelector('.informations')) return // media

   var acceptSvg = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>',
       refuseSvg = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>',
       fileSvg = '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>',
       warningSvg = '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>'
   var message_delivery_status = message_object["delivery_status"]
   var message_direction = message_object["direction"]
   var message_id = message_object["id"]
   var message_text = message_object['text']


   if (isImage(message_text) && message_delivery_status === 'finished' && displayLinksEnabled && !forceTypeToFile) {
     // Replace the old wrapper by the downloaded image
     if (message_div.querySelector('.message_wrapper')) {
       wrapper = message_div.querySelector('.message_wrapper')
       wrapper.parentNode.removeChild(wrapper)
     }
     message_div.append(mediaInteraction(message_id, message_text))
     message_div.querySelector('img').id = message_id
     message_div.querySelector('img').msg_obj = message_object
     message_div.querySelector('img').onerror = function() {
       message_div = document.getElementById('#message_' + this.id);
       if (message_div.querySelector('.message_wrapper')) {
         wrapper = message_div.querySelector('.message_wrapper')
         wrapper.parentNode.removeChild(wrapper)
       }
       message_div.append(fileInteraction(message_id))
       updateFileInteraction(message_div, this.msg_obj, true)
     }
     return
   }

   // Set informations text
   var informations_div = message_div.querySelector(".informations");
   var informations_txt = getMessageTimestampText(message_object["timestamp"], true);
   if (message_object["totalSize"] && message_object["progress"]) {
     if (message_delivery_status === 'finished') {
       informations_txt += " - " + humanFileSize(message_object["totalSize"]);
     } else {
       informations_txt += " - " + humanFileSize(message_object["progress"])
                         + " / " + humanFileSize(message_object["totalSize"]);
     }
   }
   informations_txt += " - " + message_delivery_status;
   informations_div.innerText = informations_txt;

   // Update flat buttons
   var left_buttons = message_div.querySelector(".left_buttons");
   left_buttons.innerHTML = '';
   if (message_delivery_status === 'awaiting peer' || message_delivery_status === 'awaiting host' || message_delivery_status.indexOf('ongoing') === 0) {
     if (message_direction === 'in' && message_delivery_status.indexOf('ongoing') !== 0) {
       // add buttons to accept or refuse a call.
       var accept_button = document.createElement('div');
       accept_button.innerHTML = acceptSvg;
       accept_button.setAttribute("title", "Accept");
       accept_button.setAttribute("class", "flat-button accept");
       accept_button.onclick = function() {
         window.prompt('ACCEPT_FILE:' + message_id);
       }
       left_buttons.appendChild(accept_button);
     }
     var refuse_button = document.createElement('div');
     refuse_button.innerHTML = refuseSvg;
     refuse_button.setAttribute("title", "Refuse");
     refuse_button.setAttribute("class", "flat-button refuse");
     refuse_button.onclick = function() {
       window.prompt('REFUSE_FILE:' + message_id);
     }
     left_buttons.appendChild(refuse_button);
   } else {
     var status_button = document.createElement('div');
     var statusFile = fileSvg;
     if (isErrorStatus(message_delivery_status))
       statusFile = warningSvg;
     status_button.innerHTML = statusFile;
     status_button.setAttribute("class", "flat-button");
     left_buttons.appendChild(status_button);
   }

   message_div.querySelector('.full').innerText = message_text
   message_div.querySelector('.filename').innerText = message_text.split('/').pop()
   message_div.querySelector('.filename').innerText = message_text.split('/').pop()
   updateProgressBar(message_div.querySelector('.message_progress_bar'), message_object);
   updateProgressBar(message_div.querySelector('.message_progress_bar'), message_object);
 }

/**
 * Return if a file is an image
 * @param file
 */
function isImage(file) {
  return file.toLowerCase().match(/\.(jpeg|jpg|gif|png)$/) !== null
}

/**
 * Return if a file is a youtube video
 * @param file
 */
function isVideo(file) {
  const availableProtocols = ['http:', 'https:']
  const videoHostname = ['youtube.com', 'www.youtube.com', 'youtu.be']
  const urlParser = document.createElement('a')
  urlParser.href = file
  return (availableProtocols.includes(urlParser.protocol) && videoHostname.includes(urlParser.hostname))
}

/**
 * Try to show an image or a video link (youtube for now)
 * @param message_id
 * @param link to show
 * @param ytid if it's a youtube video
 */
function mediaInteraction(message_id, link, ytid, noerror) {
  // TODO promise?
  // Try to display images.
  const media_wrapper = document.createElement('div')
  media_wrapper.setAttribute('class', 'media_wrapper')
  const linkElt = document.createElement('a')
  linkElt.href = link
  linkElt.style = 'text-decoration: none;'
  const imageElt = document.createElement('img')
  // Note, here, we don't check the size of the image.
  // in the future, we can check the content-type and content-length with a request
  // and maybe disable svg
  if (noerror)
    imageElt.setAttribute('onerror', 'this.style.display=\'none\'')
  if (ytid) {
    imageElt.src = `http://img.youtube.com/vi/${ytid}/0.jpg`
  } else {
    imageElt.src = link
  }
  linkElt.appendChild(imageElt)
  if (ytid) {
    const containerElt = document.createElement('div');
    containerElt.setAttribute('class', 'containerVideo');
    const playDiv = document.createElement('div')
    playDiv.setAttribute('class', 'playVideo')
    playDiv.innerHTML = '<svg fill="#ffffff" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">\
        <path d="M8 5v14l11-7z"/>\
        <path d="M0 0h24v24H0z" fill="none"/>\
    </svg>'
    linkElt.appendChild(playDiv)
    containerElt.appendChild(linkElt)
    media_wrapper.appendChild(containerElt)
  } else {
    media_wrapper.appendChild(linkElt)
  }
  return media_wrapper
}

/**
 * Build a new text interaction
 * @param message_id
 * @param htmlText the DOM to show
 */
function textInteraction(message_id, htmlText) {
  const message_wrapper = document.createElement('div')
  message_wrapper.setAttribute('class', 'message_wrapper')
  var message_text = document.createElement('span')
  message_text.setAttribute('class', 'message_text')
  message_text.innerHTML = htmlText
  message_wrapper.appendChild(message_text)
  // TODO STATUS
  return message_wrapper
}

/**
 * Update a text interaction (text)
 * @param message_div the message to update
 * @param delivery_status the status of the message
 * @TODO retry button
 */
function updateTextInteraction(message_div, delivery_status) {
  if (!message_div.querySelector('.message_text')) return // media
  switch(delivery_status)
  {
    case "ongoing":
    case "sending":
      var sending_div = message_div.querySelector('.sending')
      if (!sending_div) {
        sending_div = document.createElement('div')
        sending_div.setAttribute('class', 'sending')
        sending_div.innerHTML = '<svg overflow="hidden" viewBox="0 -2 16 14" height="16px" width="16px"><circle class="status_circle anim-first" cx="4" cy="12" r="1"/><circle class="status_circle anim-second" cx="8" cy="12" r="1"/><circle class="status_circle anim-third" cx="12" cy="12" r="1"/></svg>'
        // add sending animation to message
        message_div.appendChild(sending_div)
      }
      message_div.querySelector('.message_text').style = 'color: #888'
      break
    case "failure":
      // change text color to red
      message_div.querySelector('.message_wrapper').style = 'background-color: #f3a6a6'
      message_div.querySelector('.message_text').style = 'color: #000'
      var failure_div = message_div.querySelector('.failure')
      if (!failure_div) {
        failure_div = document.createElement('div')
        failure_div.setAttribute('class', 'failure')
        failure_div.innerHTML = '<svg overflow="visible" viewBox="0 -2 16 14" height="16px" width="16px"><path class="status-x x-first" stroke="#AA0000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" d="M4,4 L12,12"/><path class="status-x x-second" stroke="#AA0000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" d="M12,4 L4,12"/></svg>'
        // add failure animation to message
        message_div.appendChild(failure_div)
      }
      var sending = message_div.querySelector('.sending')
      if (sending) sending.style.visibility = 'hidden'
      break
    case "sent":
    case "finished":
    case "unknown":
    case "read":
      // change text color to black
      message_div.querySelector('.message_text').style = 'color: #000'
      var sending = message_div.querySelector('.sending')
      if (sending) sending.style.visibility = 'hidden'
      break
    default:
      console.log("getMessageDeliveryStatusText: unknown delivery status: " + delivery_status)
      break
  }
}

/**
 * Build a new interaction (call or contact)
 * @param message_id
 */
function actionInteraction(message_id) {
  var message_wrapper = document.createElement('div')
  message_wrapper.setAttribute('class', 'message_wrapper')

  // An file interaction contains buttons at the left of the interaction
  // for the status or accept/refuse
  var left_buttons = document.createElement('div')
  left_buttons.setAttribute('class', 'left_buttons')
  message_wrapper.appendChild(left_buttons)
  // Also contains a bold clickable text
  var text_div = document.createElement('div')
  text_div.setAttribute('class', 'text')
  message_wrapper.appendChild(text_div)
  return message_wrapper
}

/**
 * Update a call interaction (icon + text)
 * @param message_div the message to update
 * @param message_object new informations
 */
function updateCallInteraction(message_div, message_object) {
  const outgoingCall = '<svg fill="#219d55" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z"/></svg>'
  const callMissed = '<svg fill="#dc2719" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.59 7L12 14.59 6.41 9H11V7H3v8h2v-4.59l7 7 9-9z"/></svg>'
  const outgoingMissed = '<svg fill="#dc2719" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M24 24H0V0h24v24z" id="a"/></defs><clipPath id="b"><use overflow="visible" xlink:href="#a"/></clipPath><path clip-path="url(#b)" d="M3 8.41l9 9 7-7V15h2V7h-8v2h4.59L12 14.59 4.41 7 3 8.41z"/></svg>'
  const callReceived = '<svg fill="#219d55" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 5.41L18.59 4 7 15.59V9H5v10h10v-2H8.41z"/></svg>'

  const message_text = message_object['text']
  const message_direction = (message_text.toLowerCase().indexOf('incoming') !== -1) ? 'in' : 'out'
  const missed = message_text.indexOf('Missed') !== -1

  message_div.querySelector('.text').innerText = message_text.substring(2)

  var left_buttons = message_div.querySelector('.left_buttons')
  left_buttons.innerHTML = ''
  var status_button = document.createElement('div')
  var statusFile = ''
  if (missed)
    statusFile = (message_direction === 'in') ? callMissed : outgoingMissed
  else
    statusFile = (message_direction === 'in') ? callReceived : outgoingCall
  status_button.innerHTML = statusFile
  status_button.setAttribute('class', 'flat-button')
  left_buttons.appendChild(status_button)
}

/**
 * Update a contact interaction (icon + text)
 * @param message_div the message to update
 * @param message_object new informations
 */
function updateContactInteraction(message_div, message_object) {
  const message_text = message_object['text']

  message_div.querySelector('.text').innerText = message_text

  var left_buttons = message_div.querySelector('.left_buttons')
  left_buttons.innerHTML = ''
  var status_button = document.createElement('div')
  status_button.innerHTML = '<?xml version="1.0" ?><svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg">\
                              <path d="M8.013766 23.107838l0.00465 -0.810382 0.033095 -0.133474c0.1495327 -0.603099 0.50107 -1.099452 1.1411917 -1.611311 0.1690725 -0.135195 0.5493165 -0.388522 0.7866284 -0.524069 1.4449359 -0.825313 3.6497829 -1.439907 5.5693029 -1.552424 0.268992 -0.01577 0.866138 -0.0085 1.131356 0.01373 1.873734 0.157215 3.884055 0.729268 5.262712 1.497544 1.031356 0.574739 1.70347 1.254543 1.937152 1.959316 0.101301 0.305518 0.100213 0.293393 0.105924 1.180132l0.0051 0.791314 -7.990878 0 -7.990878 0 0.00465 -0.810381z" fill="#000000"/>\
                              <path d="M15.641818 15.906151c-0.512638 -0.04757 -0.970838 -0.177847 -1.424519 -0.40503 -0.534623 -0.267715 -0.972855 -0.622072 -1.344489 -1.087162 -0.500329 -0.626146 -0.797007 -1.385268 -0.858271 -2.196087 -0.01377 -0.182277 -0.0068 -0.568261 0.01341 -0.738308 0.137062 -1.155519 0.73576 -2.1602655 1.685808 -2.8291565 1.010233 -0.711264 2.333521 -0.90809 3.519055 -0.523424 0.511977 0.166119 0.9845 0.434474 1.39324 0.791249 0.103105 0.09 0.316993 0.304905 0.402137 0.404056 0.848222 0.9877635 1.16007 2.3144245 0.843044 3.5864705 -0.116312 0.466694 -0.339476 0.947863 -0.621858 1.340798 -0.695617 0.967955 -1.761735 1.568261 -2.95044 1.661324 -0.155481 0.01217 -0.501821 0.0097 -0.657113 -0.0047z" fill="#000000"/>\
                              </svg>'
  status_button.setAttribute('class', 'flat-button')
  left_buttons.appendChild(status_button)
}

/**
 * Add a message to the conversation.
 * @param message_object to treat
 * @param new_message if it's a new message or if we need to update
 * @param insert_after if we want the message at the end or the top of the conversation
 */
function addOrUpdateMessage(message_object, new_message, insert_after = true) {
  const message_id = message_object['id']
  const message_type = message_object['type']
  const message_text = message_object['text']
  const message_direction = message_object['direction']
  const message_timestamp = message_object['timestamp']
  const delivery_status = message_object['delivery_status']
  const message_sender_contact_method = message_object['sender_contact_method']

  var message_div = document.querySelector('#message_' + message_id);
  var type = ''
  if (new_message) {
    // Build new message
    var classes = [
        'message',
        `message_${message_direction}`,
        `message_type_${message_type}`
    ]

    message_div = document.createElement('div')
    message_div.setAttribute('id', `message_${message_id}`)
    message_div.setAttribute('class', classes.join(' '))

    // Build message for each types.
    // Add sender images if necessary (like if the interaction doesn't take the whole width)
    const need_sender = (message_type === 'data_transfer' || message_type === 'text');
    if (need_sender) {
      var message_sender_image = document.createElement('span')
      message_sender_image.setAttribute('class', `sender_image sender_image_${message_sender_contact_method}`)
      message_div.appendChild(message_sender_image)
    }

    // Build main content
    if (message_type === 'data_transfer') {
      if (isImage(message_text) && delivery_status === 'finished' && displayLinksEnabled) {
        message_div.append(mediaInteraction(message_id, message_text, null, false))
        message_div.querySelector('img').id = message_id
        message_div.querySelector('img').msg_obj = message_object
        message_div.querySelector('img').onerror = function() {
          message_div = document.getElementById('#message_' + this.id);
          if (message_div.querySelector('.message_wrapper')) {
            wrapper = message_div.querySelector('.message_wrapper')
            wrapper.parentNode.removeChild(wrapper)
          }
          message_div.append(fileInteraction(message_id))
          updateFileInteraction(message_div, this.msg_obj, true)
        }
      } else {
        message_div.append(fileInteraction(message_id))
      }
    } else if (message_type === 'text') {
      // TODO add the possibility to update messages (remove and rebuild)
      const htmlText = getMessageHtml(message_text)
      if (displayLinksEnabled) {
        const parser = new DOMParser();
        const DOMMsg = parser.parseFromString(htmlText, 'text/xml');
        const links = DOMMsg.querySelectorAll('a');
        if (DOMMsg.childNodes.length && links.length) {
          var isTextToShow = (DOMMsg.childNodes[0].childNodes.length > 1)
          const ytid = (isVideo(message_text))? youtube_id(message_text) : ''
          if (!isTextToShow && (ytid || isImage(message_text))) {
            type = 'media'
            message_div.append(mediaInteraction(message_id, message_text, ytid))
          }
        }
      }
      if (type !== 'media') {
        type = 'text'
        message_div.append(textInteraction(message_id, htmlText))
      }
    } else if (message_type === 'call' || message_type === 'contact') {
      message_div.append(actionInteraction(message_id))
    } else {
      const temp = document.createElement('div')
      temp.innerText = message_type
      message_div.appendChild(temp)
    }

    // Get timestamp to add
    const formattedTimestamp = getMessageTimestampText(message_timestamp, true)
    // Create the timestamp object
    const date_elt = document.createElement('div')
    date_elt.innerText = formattedTimestamp
    if (message_type === 'call' || message_type === 'contact') {
      timestamp_div_classes = [
        'timestamp',
        `timestamp_action`
      ]
    } else {
      timestamp_div_classes = [
        'timestamp',
        `timestamp_${message_direction}`
      ]
    }
    date_elt.setAttribute('class', timestamp_div_classes.join(' '))
    date_elt.setAttribute('message_timestamp', message_timestamp)
    // Remove last timestamp if it's the same<h6></h6>
    if (messages.querySelectorAll('.timestamp'))
        cleanPreviousTimestamps(date_elt, messages.children.length)

    // Add message and the new timestamp
    if (insert_after) {
      if (message_type === 'call' || message_type === 'contact') {
        message_div.querySelector('.message_wrapper').appendChild(date_elt)
        messages.appendChild(message_div)
      } else {
        messages.appendChild(message_div)
        messages.appendChild(date_elt)
      }
    } else {
      if (message_type === 'call' || message_type === 'contact') {
        message_div.querySelector('.message_wrapper').appendChild(date_elt)
        messages.insertBefore(message_div, messages.firstChild)
      } else {
        messages.insertBefore(date_elt, messages.firstChild)
        messages.insertBefore(message_div, messages.firstChild)
      }
    }
  }

  // Update informations if needed
  if (message_type === 'data_transfer')
    updateFileInteraction(message_div, message_object)
  if (message_type === 'text' && message_direction === 'out')
    // Modify sent status if necessary
    updateTextInteraction(message_div, delivery_status)
  if (message_type === 'call')
    updateCallInteraction(message_div, message_object)
  if (message_type === 'contact')
    updateContactInteraction(message_div, message_object)

  // Clean timestamps
  updateTimestamps();
}


/**
 * Add a message to the buffer
 */
function addMessage(message_object)
{
    var atEnd = messages.scrollTop >= messages.scrollHeight - messages.clientHeight - 5;
    addOrUpdateMessage(message_object, true);
    if (atEnd) {
        var startTime = Date.now(),
            durTime = 250.,
            scrollStartHeight = messages.scrollHeight,
            scrollStart = messages.scrollTop,
            scrollDiff = scrollStartHeight - messages.clientHeight - scrollStart;

        function loop() {
            var time = Date.now() - startTime,
                scrollHeight = messages.scrollHeight,
                diff = messages.scrollTop - scrollStart; // If user scrolls up (diff > 0).

            if (time >= durTime || scrollHeight != scrollStartHeight || diff < 0) {
                if (diff >= 0) { // User scrolled up, don't autoscroll.
                    messages.scrollTop = scrollHeight;
                }
                return false;
            } else {
                messages.scrollTop = scrollStart + (scrollDiff * (time/durTime));
                raf(loop);
            }
        }
        raf(loop); // Start the animation loop
    }
}

/**
 * Show the history in reverse order and avoid the process to consumes a lot of ressources
 */
function printHistoryPart () {
  if(historyBuffer.length == 0) {
      // nothing to print
      return;
  }

  var previousScrollHeightMinusTop = messages.scrollHeight - messages.scrollTop;
  // Show 10 messages
  for (var i = 0; i < 10; ++i) {
    addOrUpdateMessage(historyBuffer[historyBuffer.length - 1 - historyBufferIndex], true, false);
    historyBufferIndex ++;
    if (historyBufferIndex === historyBuffer.length)
      break;
  }
  // Replace the scrollbar to the wanted position
  messages.scrollTop = messages.scrollHeight - previousScrollHeightMinusTop;
  // Make a short pause to minimizes ressources consumption
  // show quickly the first hundred messages
  if (historyBufferIndex !== historyBuffer.length)
    setTimeout(printHistoryPart, (historyBufferIndex > 100) ? 100 : 1);
}

/**
 * Show the whole history in the chatview.
 */
function printHistory(messages_array)
{
    historyBuffer = messages_array;
    historyBufferIndex = 0;
    setTimeout(printHistoryPart, 1);
}

/**
 * Updated a message that was previously added with addMessage
 */
function updateMessage(message_object)
{
    addOrUpdateMessage(message_object, false);
}

/**
 * Sets the image for a given sender
 * set_sender_image object should contain the following keys:
 * - sender: the name of the sender
 * - sender_image: base64 png encoding of the sender image
 */
function setSenderImage(set_sender_image_object)
{
    var sender_contact_method = set_sender_image_object['sender_contact_method'],
        sender_image = set_sender_image_object['sender_image'],
        sender_image_id = "sender_image_" + sender_contact_method,
        currentSenderImage = document.getElementById("#" + sender_image_id), // Remove the currently set sender image
        style;

    if (currentSenderImage) {
        currentSenderImage.parentNode.removeChild(currentSenderImage);
    }

    // Create a new style element
    style = document.createElement('style');

    style.type = 'text/css';
    style.id = sender_image_id;
    style.innerHTML = '.' + sender_image_id + " { \n content: url(data:image/png;base64," + sender_image + "); \n height: 35px; \n width: 35px; \n }";
    document.head.appendChild(style);
}

/**
 * Change the send icon
 */
function setSendIcon(source)
{
    sendBtn.src = "data:image/png;base64," + source;
}

function clearSenderImages()
{
    var styles = document.head.querySelectorAll("style"),
        i = styles.length;

    while (i--){
      document.head.removeChild(styles[i]);
    }
}

function setTemporary(temporary)
{
  if (temporary) {
      messageBarInput.placeholder = "Note: an interaction will create a new contact.";
  } else {
      messageBarInput.placeholder = "Type a message";
  }
}

function sendFile()
{
  window.prompt('SEND_FILE');
}

</script>

</html>
