/////////////////////////////////////////////////////////////////////////////
// Name:        cachedfs_inet.cpp
// Purpose:     HTTP and FTP file system
// Author:      Vaclav Slavik
// Modified by: Francesco Montorsi
// Copyright:   (c) 1999 Vaclav Slavik
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WXPRECOMP
    #include "wx/wx.h"
#endif

#include "wx/wfstream.h"
#include "wx/url.h"
#include "wx/filesys.h"
#include "wx/module.h"

#include "wx/cachedfs_inet.h"


// ----------------------------------------------------------------------------
// wxCachedInternetFSHandler
// ----------------------------------------------------------------------------

static wxString StripProtocolAnchor(const wxString& location)
{
    wxString myloc(location.BeforeLast(wxT('#')));
    if (myloc.empty()) myloc = location.AfterFirst(wxT(':'));
    else myloc = myloc.AfterFirst(wxT(':'));

    // fix malformed url:
    if (!myloc.Left(2).IsSameAs(wxT("//")))
    {
        if (myloc.GetChar(0) != wxT('/')) myloc = wxT("//") + myloc;
        else myloc = wxT("/") + myloc;
    }
    if (myloc.Mid(2).Find(wxT('/')) == wxNOT_FOUND) myloc << wxT('/');

    return myloc;
}

bool wxCachedInternetFSHandler::CanOpen(const wxString& location)
{
    wxString p = GetProtocol(location);
    if ((p == wxT("http")) || (p == wxT("ftp")))
    {
        wxURL url(p + wxT(":") + StripProtocolAnchor(location));
        return (url.GetError() == wxURL_NOERR);
    }

    return false;
}


wxFSFile* wxCachedInternetFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs),
                                              const wxString& location)
{
    wxString right =
        GetProtocol(location) + wxT(":") + StripProtocolAnchor(location);

    if (m_cache.count(right) > 0)
    {
        wxLogDebug(wxT("Getting from cache the resource at %s"), right.c_str());
        const wxFSFileRawData *d = m_cache[right];

        // create a new wxFSFile from cached data
        wxInputStream *stream =
            new wxMemoryInputStream(d->GetData(), d->GetLen());
        return new wxFSFile(stream,
                            d->GetLocation(),
                            d->GetMimeType(),
                            d->GetAnchor(),
                            d->GetModificationTime());
    }

    wxURL url(right);
    if (url.GetError() == wxURL_NOERR)
    {
        wxInputStream *s = url.GetInputStream();
        wxString content = url.GetProtocol().GetContentType();
        if (content == wxEmptyString) content = GetMimeTypeFromExt(location);
        if (s)
        {
            // download resource and put it in a memory stream
            wxFSFileRawData *d =
                new wxFSFileRawData(s->GetSize(), right, content,
                                    GetAnchor(location), wxDateTime::Now());
            if (s->Read(d->GetData(), d->GetLen()).LastRead() != s->GetSize())
                return NULL;

            wxDELETE(s);
            m_cache[right] = d;

            wxInputStream *stream =
                new wxMemoryInputStream(d->GetData(), d->GetLen());
            return new wxFSFile(stream,
                                d->GetLocation(),
                                d->GetMimeType(),
                                d->GetAnchor(),
                                d->GetModificationTime());
        }
    }

    return (wxFSFile*) NULL; // incorrect URL
}

