module JamRuby
  class ChatMessage < ActiveRecord::Base
    include HtmlSanitize
    html_sanitize strict: [:message]

    CHANNEL_SESSION = 'session'
    CHANNEL_LESSON = 'lesson'
    self.table_name = 'chat_messages'
    self.primary_key = 'id'

    default_scope { order('created_at DESC') }

    attr_accessor :ignore_message_checks

    attr_accessible :user_id, :message, :music_session_id

    belongs_to :user
    belongs_to :music_session
    belongs_to :target_user, class_name: "JamRuby::User"
    belongs_to :lesson_session, class_name: "JamRuby::LessonSession"
    belongs_to :music_notation, class_name: "JamRuby::MusicNotation"
    belongs_to :claimed_recording, class_name: "JamRuby::ClaimedRecording"

    validates :user, presence: true
    validates :message, length: {minimum: 1, maximum: 255}, no_profanity: true, unless: :ignore_message_checks

    validate :same_school_protection
    validate :no_global_for_schools

    def no_global_for_schools
      if self.channel == 'global' && user && !user.school_id.nil?
        errors.add(:user, ValidationMessages::DISABLED_GLOBAL_SCHOOL_CHAT)
      end
    end

    def same_school_protection
      if user && target_user
        if !user.is_platform_instructor && !target_user.is_platform_instructor
          if user.school_id != target_user.school_id
            errors.add(:target_user, ValidationMessages::CAN_ONLY_CHAT_SAME_SCHOOL)
          end
        end
      end
    end

    def self.create(user, music_session, message, channel, client_id, target_user = nil, lesson_session = nil, purpose = nil, music_notation = nil, recording = nil)
      source_user = user

      if lesson_session # force the messaging to be to/from
        if user.id != lesson_session.student_id
          source_user = lesson_session.teacher
          target_user = lesson_session.student
        else
          source_user = lesson_session.student
          target_user = lesson_session.teacher
        end

      end
      chat_msg = ChatMessage.new
      chat_msg.user_id = source_user.id
      chat_msg.music_session_id = music_session.id if music_session
      chat_msg.message = message
      chat_msg.channel = channel
      chat_msg.target_user = target_user
      chat_msg.lesson_session = lesson_session
      chat_msg.purpose = purpose
      chat_msg.music_notation = music_notation
      chat_msg.claimed_recording = recording

      if purpose == 'Notation File' || purpose == 'Audio File' || purpose == 'JamKazam Recording'
        chat_msg.ignore_message_checks = true
      end

      if lesson_session
        chat_msg.ignore_message_checks = true

        if source_user.id == lesson_session.student.id
          lesson_session.teacher_unread_messages = true
          target = lesson_session.teacher
          Notification.send_lesson_message('chat', lesson_session, false, message)
        else
          lesson_session.student_unread_messages = true
          target = lesson_session.student
          Notification.send_lesson_message('chat', lesson_session, true, message)
        end

        lesson_session.save(validate: false)

        # a nil purpose means 'normal chat', which is the only time we should send an email
        if !target.online? && message.present?
          UserMailer.lesson_chat(chat_msg).deliver_now
        end
      end

      if chat_msg.save
        ChatMessage.send_chat_msg music_session, chat_msg, source_user, client_id, channel, lesson_session, purpose, target_user, music_notation, recording
      else
        puts "Chat Message Save Error #{chat_msg.errors.inspect}"
      end

      chat_msg
    end

    class << self

      @@mq_router = MQRouter.new
      @@message_factory = MessageFactory.new

      def index(user, params = {})
        # TODO: school user scan't see chat
        if params[:channel] == 'global' && !user.school_id.nil?
          return [[], nil]
        end

        limit = params[:limit]
        limit ||= 20
        limit = limit.to_i

        start = params[:start].presence
        start = start.to_i || 0

        query = ChatMessage.where('channel = ?', params[:channel])

        if params.has_key? (:music_session)
          music_session_id = params[:music_session]
          query = ChatMessage.where('music_session_id = ?', music_session_id)
        end

        if params.has_key? (:lesson_session)
          lesson_session_id = params[:lesson_session]
          query = ChatMessage.where('lesson_session_id = ?', lesson_session_id)
        end

        query = query.offset(start).limit(limit).order('created_at DESC').includes([:user])

        if query.length == 0
          [query, nil]
        elsif query.length < limit
          [query, nil]
        else
          [query, start + limit]
        end
      end


      def send_chat_msg(music_session, chat_msg, user, client_id, channel, lesson_session, purpose, target_user, music_notation, claimed_recording)

        music_session_id = music_session.id if music_session
        lesson_session_id = lesson_session.id if lesson_session

        if music_notation
          attachment_id = music_notation.id
          attachment_type = music_notation.attachment_type
          attachment_name = music_notation.file_name
        elsif claimed_recording
          if purpose == 'Video Uploaded'
            attachment_id = claimed_recording.video_id
            attachment_type = 'video'
          else
            attachment_id = claimed_recording.id
            attachment_type = 'recording'
            attachment_name = claimed_recording.name

          end
        end



        msg = @@message_factory.chat_message(
            music_session_id,
            user.name,
            user.id,
            chat_msg.message,
            chat_msg.id,
            chat_msg.created_at.utc.iso8601,
            channel,
            lesson_session_id,
            purpose,
            attachment_id,
            attachment_type,
            attachment_name
        )

        if channel == 'session'
          @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
        elsif channel == 'global'
          @@mq_router.publish_to_active_clients(msg)
        elsif channel == 'lesson'
          @@mq_router.publish_to_user(target_user.id, msg, sender = {:client_id => client_id}) if target_user
          @@mq_router.publish_to_user(user.id, msg, sender = {:client_id => client_id}) if user
        end

      end
    end
  end
end