/***************************************************************************************
 *
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 *
 *  By downloading, copying, installing or using the software you agree to this license.
 *  If you do not agree to this license, do not download, install, 
 *  copy or use the software.
 *
 *  Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
 *
 *  Redistribution and use in binary forms, with or without modification, are permitted.
 *
 *  Unless required by applicable law or agreed to in writing, software distributed 
 *  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 *  language governing permissions and limitations under the License.
 *
****************************************************************************************/

#include "http_mjpeg_player.h"
#include "utils.h"

/***************************************************************************************/

int http_mjpeg_notify_callback(int evt, void * puser)
{
    CHttpMjpegPlayer * pPlayer = (CHttpMjpegPlayer *) puser;
    
    pPlayer->onNotify(evt);
    return 0;
}

int http_mjpeg_video_callback(uint8 * pdata, int len, void *puser)
{
    CHttpMjpegPlayer * pPlayer = (CHttpMjpegPlayer *) puser;

    pPlayer->onVideo(pdata, len, 0);
    return 0;
}


/***************************************************************************************/

CHttpMjpegPlayer::CHttpMjpegPlayer(): CVideoPlayer()
{
    memset(m_ip, 0, sizeof(m_ip));
}

CHttpMjpegPlayer::~CHttpMjpegPlayer()
{
    close();
}

std::string CHttpMjpegPlayer::createNewMJPEGUrl(const std::string& username,
    const std::string& password,
    const std::string& url) {
    // Copy the original strings to avoid modifying the originals
    std::string modUsername = username;
    std::string modPassword = password;

    // Replace '@' with '_' in username and password
    std::replace(modUsername.begin(), modUsername.end(), '@', '_');
    std::replace(modPassword.begin(), modPassword.end(), '@', '_');

    // Extract the protocol and rest of the URL
    size_t protocolEndPos = url.find("://") + 3; // Find the position right after "://"
    std::string protocol = url.substr(0, protocolEndPos); // Include "://"

    // Construct the new URL with modified credentials
    std::string newUrl = protocol;
    newUrl += modUsername + ":" + modPassword + "@";
    newUrl += url.substr(protocolEndPos);
    return newUrl;
}
BOOL CHttpMjpegPlayer::open(std::string fileName)
{
    close();

    CVideoPlayer::open(fileName);

    char host[100];

    url_split(fileName.c_str(), NULL, 0, NULL, 0, NULL, 0, host, sizeof(host), NULL, NULL, 0);

    if (host[0] == '\0')
    {
        return FALSE;
    }

	strncpy(m_ip, host, sizeof(m_ip) - 1);

	m_httpmjpeg.set_notify_cb(http_mjpeg_notify_callback, this);
    m_httpmjpeg.set_video_cb(http_mjpeg_video_callback);

	return TRUE;
}

BOOL CHttpMjpegPlayer::open(std::string _username, std::string _password, std::string _url)
{
    close();

    CVideoPlayer::open(_username, _password, _url);

    char host[100];
    std::string fileName = createNewMJPEGUrl(_username, _password, _url);

    url_split(fileName.c_str(), NULL, 0, NULL, 0, NULL, 0, host, sizeof(host), NULL, NULL, 0);

    if (host[0] == '\0')
    {
        return FALSE;
    }

    strncpy(m_ip, host, sizeof(m_ip) - 1);

    m_httpmjpeg.set_notify_cb(http_mjpeg_notify_callback, this);
    m_httpmjpeg.set_video_cb(http_mjpeg_video_callback);

    return TRUE;
}
void CHttpMjpegPlayer::close()
{
	// stop http-mjpeg connection
	m_httpmjpeg.mjpeg_stop();
	m_httpmjpeg.mjpeg_close();

    m_bPlaying = FALSE;
    m_bPaused = FALSE;
    CVideoPlayer::StopVideoDecoder();

    CVideoPlayer::close();
}
void  CHttpMjpegPlayer::setBbox(cv::Rect bbox) {
    CVideoPlayer::setBbox(bbox);
}
void  CHttpMjpegPlayer::setCrop(bool crop) {
    CVideoPlayer::setCrop(crop);
}
BOOL CHttpMjpegPlayer::play()
{
	if (m_httpmjpeg.mjpeg_start(m_sFileName.c_str(), m_acct.c_str(), m_pass.c_str()))
    {
        m_bPlaying = TRUE;
        m_bPaused = FALSE;
    }
    CVideoPlayer::StartVideoDecoder();// Start the video decoder
    return m_bPlaying;
}

void CHttpMjpegPlayer::stop()
{
    if (m_bPlaying || m_bPaused)
    {
        m_httpmjpeg.mjpeg_stop();
    }
    // Set flags BEFORE stopping decoder so rx thread stops calling decode()
    m_bPlaying = FALSE;
    m_bPaused = FALSE;
    CVideoPlayer::StopVideoDecoder(); // Stop the video decoder
}

BOOL CHttpMjpegPlayer::pause()
{
    CVideoPlayer::StopVideoDecoder(); // Stop the video decoder
    return m_bPaused;
}

BOOL CHttpMjpegPlayer::seek(int pos)
{
    return FALSE;
}

int CHttpMjpegPlayer::getVideoCodec()
{
    return VIDEO_CODEC_JPEG;
}

void CHttpMjpegPlayer::onNotify(int evt)
{
	if (evt == MJPEG_EVE_CONNSUCC)
	{
        openVideo(VIDEO_CODEC_JPEG);
	}

}

void CHttpMjpegPlayer::onVideo(uint8 * pdata, int len, uint32 ts)
{
    playVideo(pdata, len, ts, 0);
}

BOOL CHttpMjpegPlayer::onRecord()
{
    avi_set_video_info(m_pAviCtx, 0, 0, 0, "JPEG");

    avi_update_header(m_pAviCtx);
    
	return TRUE;
}





