/*
 * Devices support using the MacOS Disk Arbitration library.
 *
 * Copyright 2006 Alexandre Julliard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include "wine/port.h"

#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/time.h>

#include "mountmgr.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);

#ifdef HAVE_DISKARBITRATION_DISKARBITRATION_H

#include <DiskArbitration/DiskArbitration.h>

static void appeared_callback( DADiskRef disk, void *context )
{
    CFDictionaryRef dict = DADiskCopyDescription( disk );
    const void *ref;
    char device[64];
    char mount_point[PATH_MAX];
    enum device_type type = DEVICE_UNKNOWN;

    if (!dict) return;

    /* ignore non-removable devices */
    if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaRemovable") )) ||
        !CFBooleanGetValue( ref )) goto done;

    /* get device name */
    if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done;
    strcpy( device, "/dev/r" );
    CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII );

    if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumePath") )))
        CFURLGetFileSystemRepresentation( ref, true, (UInt8 *)mount_point, sizeof(mount_point) );
    else
        mount_point[0] = 0;

    if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumeKind") )))
    {
        if (!CFStringCompare( ref, CFSTR("cd9660"), 0 ) ||
            !CFStringCompare( ref, CFSTR("udf"), 0 ))
            type = DEVICE_CDROM;
    }

    TRACE( "got mount notification for '%s' on '%s'\n", device, mount_point );

    add_dos_device( -1, device, device, mount_point, type );
done:
    CFRelease( dict );
}

static void changed_callback( DADiskRef disk, CFArrayRef keys, void *context )
{
    appeared_callback( disk, context );
}

static void disappeared_callback( DADiskRef disk, void *context )
{
    CFDictionaryRef dict = DADiskCopyDescription( disk );
    const void *ref;
    char device[100];

    if (!dict) return;

    /* ignore non-removable devices */
    if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaRemovable") )) ||
        !CFBooleanGetValue( ref )) goto done;

    /* get device name */
    if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done;
    strcpy( device, "/dev/r" );
    CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII );

    TRACE( "got unmount notification for '%s'\n", device );

    remove_dos_device( -1, device );
done:
    CFRelease( dict );
}

static DWORD WINAPI runloop_thread( void *arg )
{
    DASessionRef session = DASessionCreate( NULL );

    if (!session) return 1;

    DASessionScheduleWithRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
    DARegisterDiskAppearedCallback( session, kDADiskDescriptionMatchVolumeMountable,
                                    appeared_callback, NULL );
    DARegisterDiskDisappearedCallback( session, kDADiskDescriptionMatchVolumeMountable,
                                       disappeared_callback, NULL );
    DARegisterDiskDescriptionChangedCallback( session, kDADiskDescriptionMatchVolumeMountable,
                                              kDADiskDescriptionWatchVolumePath, changed_callback, NULL );
    CFRunLoopRun();
    DASessionUnscheduleFromRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
    CFRelease( session );
    return 0;
}

void initialize_diskarbitration(void)
{
    HANDLE handle;

    if (!(handle = CreateThread( NULL, 0, runloop_thread, NULL, 0, NULL ))) return;
    CloseHandle( handle );
}

#else  /*  HAVE_DISKARBITRATION_DISKARBITRATION_H */

void initialize_diskarbitration(void)
{
    TRACE( "Skipping, Disk Arbitration support not compiled in\n" );
}

#endif  /* HAVE_DISKARBITRATION_DISKARBITRATION_H */
