/*
 * Copyright (C) 2022 Savoir-faire Linux Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <https://www.gnu.org/licenses/>.
 */
import { Stack } from '@mui/system';
import dayjs from 'dayjs';
import dayOfYear from 'dayjs/plugin/dayOfYear';
import isBetween from 'dayjs/plugin/isBetween';
import { useMemo } from 'react';

import {
  MessageBubblesGroup,
  MessageCall,
  MessageDate,
  MessageInitial,
  MessageMember,
  MessageMerge,
  MessageTime,
} from './Message';

dayjs.extend(dayOfYear);
dayjs.extend(isBetween);

export default function MessageList(props) {
  const messagesComponents = useMemo(() => buildMessagesList(props.messages), [props.messages]);

  return (
    <Stack marginLeft="16px" marginRight="16px" direction="column-reverse">
      {messagesComponents?.map(({ Component, id, props }) => (
        <Component key={id} {...props} />
      ))}
    </Stack>
  );
}

const buildMessagesList = (messages) => {
  if (messages.length == 0) {
    return null;
  }

  const components = [];
  let lastTime = dayjs.unix(messages[0].timestamp);
  let lastAuthor = messages[0].author;
  let messageBubblesGroup = [];

  const pushMessageBubblesGroup = () => {
    if (messageBubblesGroup.length == 0) {
      return;
    }
    components.push({
      id: `group-${messageBubblesGroup[0].id}`,
      Component: MessageBubblesGroup,
      props: { messages: messageBubblesGroup },
    });
    messageBubblesGroup = [];
  };

  const pushMessageCall = (message) => {
    components.push({
      id: `call-${message.id}`,
      Component: MessageCall,
      props: { message },
    });
  };

  const pushMessageMember = (message) => {
    components.push({
      id: `member-${message.id}`,
      Component: MessageMember,
      props: { message },
    });
  };

  const pushMessageMerge = (message) => {
    components.push({
      id: `merge-${message.id}`,
      Component: MessageMerge,
      props: { message },
    });
  };

  const pushMessageTime = (message, time, hasDateOnTop = false) => {
    components.push({
      id: `time-${message.id}`,
      Component: MessageTime,
      props: { time, hasDateOnTop },
    });
  };

  const pushMessageDate = (message, time) => {
    components.push({
      id: `date-${message.id}`,
      Component: MessageDate,
      props: { time },
    });
  };

  const pushMessageInitial = (message) => {
    components.push({
      id: `initial-${message.id}`,
      Component: MessageInitial,
      props: { message },
    });
  };

  messages.forEach((message) => {
    // most recent messages first
    switch (message.type) {
      case 'text/plain':
      case 'application/data-transfer+json':
        if (lastAuthor != message.author) {
          pushMessageBubblesGroup();
        }
        messageBubblesGroup.push(message);
        break;
      case 'application/call-history+json':
        pushMessageBubblesGroup();
        pushMessageCall(message);
        break;
      case 'member':
        pushMessageBubblesGroup();
        pushMessageMember(message);
        break;
      case 'merge':
        pushMessageBubblesGroup();
        pushMessageMerge(message);
        break;
      case 'initial':
      default:
        break;
    }

    const time = dayjs.unix(message.timestamp);
    if (message.type == 'initial') {
      pushMessageBubblesGroup();
      pushMessageTime(message, time, true);
      pushMessageDate(message, time);
      pushMessageInitial(message);
    } else {
      if (
        // If the date is different
        lastTime?.year() != time.year() ||
        lastTime?.dayOfYear() != time.dayOfYear()
      ) {
        pushMessageBubblesGroup();
        pushMessageTime(message, time, true);
        pushMessageDate(message, time);
      } else if (
        // If more than 5 minutes have passed since the last message
        !lastTime.isBetween(time, time?.add(5, 'minute'))
      ) {
        pushMessageBubblesGroup();
        pushMessageTime(message, time);
      }

      lastTime = time;
      lastAuthor = message.author;
    }
  });

  return components;
};
