import {Component, EventEmitter, inject, input, Output} from '@angular/core';
import {Message} from '@chatenium/chatenium-sdk/domain/dmService.schema';
import {Message as NetworkMessage} from '@chatenium/chatenium-sdk/domain/textChannelService.schema'
import {ServiceManager} from '../../../service-manager';
import {DatePipe} from '@angular/common';
import {Masonry} from '../masonry/masonry';
import {VideoPlayer} from '../video-player/video-player';
import {
  TuiButton,
  TuiDataListComponent,
  TuiDropdown,
  TuiDropdownContext,
  TuiGroup,
  TuiIcon,
  TuiOption
} from '@taiga-ui/core';
import {TranslatePipe} from '@ngx-translate/core';
import {MessageBoxViewModel} from '../message-box/message-box-viewmodel';
import {FileDataWithPreview} from '../message-box/message-box';
import {Attachment} from '@chatenium/chatenium-sdk/domain/common.schema';

@Component({
  selector: 'messages',
  imports: [
    DatePipe,
    Masonry,
    VideoPlayer,
    TuiDropdownContext,
    TuiDropdown,
    TuiButton,
    TuiOption,
    TranslatePipe,
    TuiDataListComponent,
    TuiGroup,
    TuiIcon
  ],
  templateUrl: './messages.html',
  styleUrl: './messages.scss',
})
export class Messages {
  serviceManager = inject(ServiceManager)

  messages = input.required<Message[] | NetworkMessage[]>()
  messageBoxViewModel = input.required<MessageBoxViewModel>()

  @Output() onDelete = new EventEmitter<string>()

  /**
   * Helps code readability by specifying what type of messages are being processed.
   * Example: messageAsDm(message).author == userid -- We are specifying that we are handling dm messages
   * @param message
   */
  messageAsDm(message: Message | NetworkMessage) {
    return message == undefined ? <Message>{author: "no"} : message as Message
  }

  /**
   * Helps code readability by specifying what type of messages are being processed
   Example: messageAsNetwork(message).author.userid == userid -- We are specifying that we are handling network messages
   * @param message
   */
  messageAsNetwork(message: Message | NetworkMessage) {
    return message == undefined ? <NetworkMessage>{author: {userid: "no"}} : message as NetworkMessage
  }

  isMessageStartOfChain(i: number) {
    const message = this.messages()[i];
    if (!message) return false;

    const prev = this.messages()[i - 1];

    // is author == last msg's author
    if (prev) {
      if (
        (typeof message.author === 'string' && this.messageAsDm(prev).author !== this.messageAsDm(message).author) &&
        this.messageAsNetwork(prev).author.userid !== this.messageAsNetwork(message).author.userid
      ) {
        return true;
      }

      // same author but time gap between this and prev msg
      if (
        Math.abs(message.sent_at.T - prev.sent_at.T) >= 60
      ) {
        return true;
      }
    }

    return i === 0;
  }

  isMessageMiddleInChain(i: number) {
    const message = this.messages()[i];
    if (!message || i == 0) return false;

    const prev = this.messages()[i - 1];

    // message must be from the same author and have little time gap between
    return (
      (
        (typeof message.author === 'string' && this.messageAsDm(prev).author == this.messageAsDm(message).author) ||
        this.messageAsNetwork(prev).author.userid == this.messageAsNetwork(message).author.userid
      ) &&
      Math.abs(message.sent_at.T - prev.sent_at.T) <= 60
    );
  }

  isMessageEndOfChain(i: number) {
    // prevent false positive
    if (this.isMessageStartOfChain(i)) return false;

    const message = this.messages()[i];
    if (!message) return false;

    const next = this.messages()[i + 1];

    // First condition: next author is different
    if (next) {
      if (
        (typeof message.author === 'string' && this.messageAsDm(next).author != this.messageAsDm(message).author) ||
        this.messageAsNetwork(next).author.userid != this.messageAsNetwork(message).author.userid
      ) {
        return true;
      }

      // same author but time gap between this and next msg
      if (
        Math.abs(message.sent_at.T - next.sent_at.T) >= 60
      ) {
        return true;
      }
    }

    // last message is always end
    return i + 1 === this.messages().length;
  }

  filterExpressedMedia(files: Attachment[]) {
    return files.filter(f => f.type == "image" || f.type == "video")
  }

  filterNonExpressedMedia(files: Attachment[]) {
    return files.filter(f => f.type != "image" && f.type != "video")
  }

  protected readonly Object = Object;
}
