/*
 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.media.sound;

import javax.sound.midi.MidiDevice;
import javax.sound.midi.spi.MidiDeviceProvider;


/**
 * Super class for MIDI input or output device provider.
 *
 * @author Florian Bomers
 */
public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider {

    private static boolean enabled;

    /**
     * Create objects representing all MIDI output devices on the system.
     */
    static {
        if (Printer.trace) Printer.trace("AbstractMidiDeviceProvider: static");
        Platform.initialize();
        enabled = Platform.isMidiIOEnabled();
        if (Printer.trace) Printer.trace("AbstractMidiDeviceProvider: enabled: " + enabled);

        // $$fb number of MIDI devices may change with time
        // also for memory's sake, do not initialize the arrays here
    }


    synchronized void readDeviceInfos() {
        Info[] infos = getInfoCache();
        MidiDevice[] devices = getDeviceCache();
        if (!enabled) {
            if (infos == null || infos.length != 0) {
                setInfoCache(new Info[0]);
            }
            if (devices == null || devices.length != 0) {
                setDeviceCache(new MidiDevice[0]);
            }
            return;
        }

        int oldNumDevices = (infos==null)?-1:infos.length;
        int newNumDevices = getNumDevices();
        if (oldNumDevices != newNumDevices) {
            if (Printer.trace) Printer.trace(getClass().toString()
                                             +": readDeviceInfos: old numDevices: "+oldNumDevices
                                             +"  newNumDevices: "+ newNumDevices);

            // initialize the arrays
            Info[] newInfos = new Info[newNumDevices];
            MidiDevice[] newDevices = new MidiDevice[newNumDevices];

            for (int i = 0; i < newNumDevices; i++) {
                Info newInfo = createInfo(i);

                // in case that we are re-reading devices, try to find
                // the previous one and reuse it
                if (infos != null) {
                    for (int ii = 0; ii < infos.length; ii++) {
                        Info info = infos[ii];
                        if (info != null && info.equalStrings(newInfo)) {
                            // new info matches the still existing info. Use old one
                            newInfos[i] = info;
                            info.setIndex(i);
                            infos[ii] = null; // prevent re-use
                            newDevices[i] = devices[ii];
                            devices[ii] = null;
                            break;
                        }
                    }
                }
                if (newInfos[i] == null) {
                    newInfos[i] = newInfo;
                }
            }
            // the remaining MidiDevice.Info instances in the infos array
            // have become obsolete.
            if (infos != null) {
                for (int i = 0; i < infos.length; i++) {
                    if (infos[i] != null) {
                        // disable this device info
                        infos[i].setIndex(-1);
                    }
                    // what to do with the MidiDevice instances that are left
                    // in the devices array ?? Close them ?
                }
            }
            // commit new list of infos.
            setInfoCache(newInfos);
            setDeviceCache(newDevices);
        }
    }


    public MidiDevice.Info[] getDeviceInfo() {
        readDeviceInfos();
        Info[] infos = getInfoCache();
        MidiDevice.Info[] localArray = new MidiDevice.Info[infos.length];
        System.arraycopy(infos, 0, localArray, 0, infos.length);
        return localArray;
    }


    public MidiDevice getDevice(MidiDevice.Info info) {
        if (info instanceof Info) {
            readDeviceInfos();
            MidiDevice[] devices = getDeviceCache();
            Info[] infos = getInfoCache();
            Info thisInfo = (Info) info;
            int index = thisInfo.getIndex();
            if (index >= 0 && index < devices.length && infos[index] == info) {
                if (devices[index] == null) {
                    devices[index] = createDevice(thisInfo);
                }
                if (devices[index] != null) {
                    return devices[index];
                }
            }
        }

        throw new IllegalArgumentException("MidiDevice " + info.toString()
                                           + " not supported by this provider.");
    }


    // INNER CLASSES


    /**
     * Info class for MidiDevices.  Adds an index value for
     * making native references to a particular device.
     */
    static class Info extends MidiDevice.Info {
        private int index;

        Info(String name, String vendor, String description, String version, int index) {
            super(name, vendor, description, version);
            this.index = index;
        }

        boolean equalStrings(Info info) {
            return      (info != null
                         && getName().equals(info.getName())
                         && getVendor().equals(info.getVendor())
                         && getDescription().equals(info.getDescription())
                         && getVersion().equals(info.getVersion()));
        }

        int getIndex() {
            return index;
        }

        void setIndex(int index) {
            this.index = index;
        }

    } // class Info


    // ABSTRACT METHODS

    abstract int getNumDevices();
    abstract MidiDevice[] getDeviceCache();
    abstract void setDeviceCache(MidiDevice[] devices);
    abstract Info[] getInfoCache();
    abstract void setInfoCache(Info[] infos);

    abstract Info createInfo(int index);
    abstract MidiDevice createDevice(Info info);
}
