#ifndef CHAT_WINDOW_H
#define CHAT_WINDOW_H

#include <app/Message.h>
#include <interface/Window.h>
#include <interface/TextControl.h>
#include <interface/TextView.h>

#include "util/Queue.h"
#include "util/String.h"

#include "ShareConstants.h"
#include "ReflowingTextView.h"

namespace beshare {

/* This is a semi-abstract base class; it defines a window that can be used for chat. */
/* Subclasses are ShareWindow (the main BeShare window) and PrivateChatWindow. */
class ChatWindow : public BWindow
{
public:
   ChatWindow(BRect defPos, const char * title, window_look look, window_feel feel, uint32 flags);
   ~ChatWindow();

   virtual void MessageReceived(BMessage * msg);

   virtual void DispatchMessage(BMessage * msg, BHandler * target);

   virtual void LogHelp(const char * cmd, int tokenID, int descID, ChatWindow * optEchoTo = NULL);
   virtual void LogMessage(LogMessageType type, const char * text, const char * optSessionID=NULL, const rgb_color * optTextColor = NULL, bool isPersonal = false, ChatWindow * optEchoTo = NULL);

   virtual bool ShowMessageTargets() const = 0;
   virtual bool ShowTimestamps(LogDestinationType d) const = 0;
   virtual bool ShowUserIDs(LogDestinationType d) const = 0;
   virtual bool OkayToLog(LogMessageType messageType, LogDestinationType destType, bool isPrivate) const = 0;

   void SetCommandURLTarget(const BMessenger & target, const BMessage & queryMessage, const BMessage & privMessage);

   void DoBeep(const char * which) const;

protected:
   void ClearChatLog() { _chatText->Clear(); }

   virtual status_t DoTabCompletion(const char * origText, String & returnCompletedText, const char * optMatchExpression) const = 0;
   virtual void GetUserNameForSession(const char * sessionID, String & retUserName) const = 0;
   virtual void GetLocalUserName(String & retLocalUserName) const = 0;
   virtual void GetLocalSessionID(String & retLocalSessionID) const = 0;
   virtual void SendChatText(String & text, ChatWindow * optEchoTo) = 0;
   virtual BView * GetChatView() const = 0;
   
   void MakeChatTextFocus() {_chatText->MakeFocus();}

   virtual void InsertChatText(LogDestinationType dest, const char * text, int textLen, text_run_array * optStyle);
   virtual void UserChatted();
   virtual void ChatTextReceivedBeep(bool isPersonal, bool mentionsName);

   void SetCustomWindowTitle(const String & title) {_customWindowTitle = title;}
   const String & GetCustomWindowTitle() const {return _customWindowTitle;}

   virtual void UpdateTitleBar() = 0;

   enum {
      CHATWINDOW_COMMAND_INIT = 'cwc0',
      CHATWINDOW_COMMAND_SEND_CHAT_TEXT,
      CHATWINDOW_COMMAND_SET_COMMAND_TARGET,
      CHATWINDOW_COMMAND_SET_CUSTOM_TITLE,
   };

   void SetFontSize(float fs) {_fontSize = fs;}
   float GetFontSize() const {return _fontSize;}

   void SetFontSize(const String & cmdString);

private:
   void InsertChatTextAux(const char * text, int textLen, text_run_array * optStyle);
   void ScrollToBottom();
   void ScrollToTop();
   bool IsScrollBarNearBottom() const;

   ReflowingTextView * _chatText;
   BScrollView * _chatScrollView;
   BTextControl * _textEntry;

   Queue<String> _chatHistory;  // last <n> Items that you previously typed in
   int _chatHistoryPosition;                    // -1, or index into (_chatHistory)
   bool _isInitialized;
   bool _isScrolling;                           // don't ScrollToBottom() when user is scrolling

   String _customWindowTitle;
   float _fontSize;
};

};  // end namespace beshare

#endif
