/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */
package org.apache.log4j.chainsaw.zeroconf;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.swing.table.AbstractTableModel;

public class ZeroConfDeviceModel extends AbstractTableModel implements ServiceListener {

    private List deviceList = new ArrayList();
    private ZeroConfPreferenceModel zeroConfPreferenceModel;
    private transient ZeroConfPlugin plugin;
    
    public ZeroConfDeviceModel() {
    }
    
    public int getRowCount() {
        return deviceList.size();
    }

    public int getColumnCount() {
        return 4;
    }

    public ServiceInfo getServiceInfoAtRow(int row) {
        return (ServiceInfo) deviceList.get(row);
    }
    public Object getValueAt(int rowIndex, int columnIndex) {
        ServiceInfo info = (ServiceInfo) deviceList.get(rowIndex);
        if(info == null) {
            return "";
        }
        switch(columnIndex) {
        case 0:
                return getAutoConnectHandle(info);
        case 1:
                return info.getAddress().getHostName() + ":" + info.getPort();
        case 2:
                return zeroConfPreferenceModel.getAutoConnectDevices().contains(getAutoConnectHandle(info))?Boolean.TRUE:Boolean.FALSE;
        case 3:
                return plugin.isConnectedTo(info)?"Connected":"Not Connected";
//                return plugin.isConnectedTo(info)?new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT):new ImageIcon();
            default:
                    return "";
        }
    }

    private String getAutoConnectHandle(ServiceInfo info) {
        return info.getName();
    }

    public void serviceAdded(ServiceEvent event) {
    }

    public void serviceRemoved(ServiceEvent event) {
        for (Iterator iter = deviceList.iterator(); iter.hasNext();) {
            ServiceInfo info = (ServiceInfo) iter.next();
            if(info.getName().equals(event.getName())) {
                iter.remove();
            }
        }
        fireTableDataChanged();
    }

    public void serviceResolved(ServiceEvent event) {
        deviceList.add(event.getInfo());
        fireTableDataChanged();
    }

    public void setZeroConfPreferenceModel(
            ZeroConfPreferenceModel zeroConfPreferenceModel) {
        this.zeroConfPreferenceModel = zeroConfPreferenceModel;
    }

    public String getColumnName(int column) {
        switch(column) {
        case 0:
                return "ZeroConf name";
        case 1:
                return "Address:Port";
        case 2:
                return "Auto-connect";
        case 3:
                return "Connection Status";
            default:
                    return "";
        }
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 2;
    }

    public Class getColumnClass(int columnIndex) {
        switch(columnIndex) {
        case 2:
               return Boolean.class;
        default:
            return super.getColumnClass(columnIndex);
        }
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if(columnIndex!=2 || !(aValue instanceof Boolean))  {
            return;
        }
        boolean autoConnect = (Boolean) aValue;
        Object device = this.deviceList.get(rowIndex);
        String autoConnectHandle = getAutoConnectHandle((ServiceInfo) device);
        if(autoConnect) {
            zeroConfPreferenceModel.getAutoConnectDevices().add(autoConnectHandle);
        }else {
            zeroConfPreferenceModel.getAutoConnectDevices().remove(autoConnectHandle);
        }
        fireTableDataChanged();
    }
    
    void setZeroConfPluginParent(ZeroConfPlugin parent) {
        this.plugin = parent;
    }


}
