/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   JUCE is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <Carbon/Carbon.h>
#include <CoreAudio/HostTime.h>
#include <sys/time.h>
#include <sys/resource.h>

BEGIN_JUCE_NAMESPACE


#include "../../../src/juce_appframework/application/juce_Application.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/basics/juce_Logger.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/misc/juce_Uuid.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"


static int64 highResTimerFrequency;

//==============================================================================
void Logger::outputDebugString (const String& text)
{
    printf ((const char*) (text + T("\n")));
}

void Logger::outputDebugPrintf (const tchar* format, ...)
{
    String text;
    va_list args;
    va_start (args, format);
    text.vprintf(format, args);
    outputDebugString (text);
}

int SystemStats::getMemorySizeInMegabytes()
{
    long bytes;
    if (Gestalt (gestaltPhysicalRAMSize, &bytes) == noErr)
        return (int) (((unsigned long) bytes) / (1024 * 1024));

    return 0;
}

const String SystemStats::getOSType()
{
    return SystemStats::MacOSX;
}

//==============================================================================
void SystemStats::initialiseStats()
{
    static bool initialised = false;

    if (! initialised)
    {
        initialised = true;

        highResTimerFrequency = (int64) AudioGetHostClockFrequency();

        if (JUCEApplication::getInstance() != 0)
        {
            RegisterAppearanceClient();

            String appName (JUCEApplication::getInstance()->getApplicationName());

            Str255 text;
            PlatformUtilities::copyToStr255 (text, appName);
            MenuRef sysMenu = NewMenu (1, text);

            InsertMenu (sysMenu, 1);
            DeleteMenu (1);
            DisposeMenu (sysMenu);
        }

        TXNInitTextension (0, 0, kTXNWantMoviesMask | kTXNWantGraphicsMask);

        String s (SystemStats::getJUCEVersion());

        rlimit lim;
        getrlimit (RLIMIT_NOFILE, &lim);
        lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
        setrlimit (RLIMIT_NOFILE, &lim);
    }
}

bool SystemStats::hasMMX()
{
    return false;
}

bool SystemStats::hasSSE()
{
    return false;
}

bool SystemStats::hasSSE2()
{
    return false;
}

bool SystemStats::has3DNow()
{
    return false;
}

const String SystemStats::getCpuVendor()
{
    return String::empty;
}

int SystemStats::getCpuSpeedInMegaherz()
{
    return GetCPUSpeed();
}


int SystemStats::getNumPhysicalCpus()
{
    return 1;
}

int SystemStats::getNumLogicalCpus()
{
    return getNumPhysicalCpus();
}

uint32 SystemStats::getPhysicalAffinityMask()
{
    jassertfalse
    return 0;
}

static int64 juce_getMicroseconds()
{
    UnsignedWide t;
    Microseconds (&t);
    return (((int64) t.hi) << 32) | t.lo;
}

uint32 juce_millisecondsSinceStartup()
{
    return (uint32) (juce_getMicroseconds() / 1000);
}

double juce_millisecondsSinceStartupHiRes()
{
    // xxx might be more accurate to use a scaled AudioGetCurrentHostTime?
    return juce_getMicroseconds() * 0.001;
}

int64 Time::getHighResolutionTicks()
{
    return (int64) AudioGetCurrentHostTime();
}

int64 Time::getHighResolutionTicksPerSecond()
{
    return highResTimerFrequency;
}

int64 SystemStats::getClockCycleCounter()
{
    jassertfalse
    return 0;
}

bool Time::setSystemTimeToThisTime() const
{
    jassertfalse
    return false;
}

const String Uuid::generateUuid()
{
    CFUUIDRef uuid = CFUUIDCreate (0);
    CFStringRef uuidString = CFUUIDCreateString (0, uuid);

    const String result (PlatformUtilities::cfStringToJuceString (uuidString));

    CFRelease (uuidString);
    CFRelease (uuid);

    return result;
}

int SystemStats::getPageSize()
{
    jassertfalse
    return 512; //xxx
}

void PlatformUtilities::fpuReset()
{
}

END_JUCE_NAMESPACE
