/*
 *  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.polygene.envisage.detail;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import org.apache.polygene.api.composite.CompositeDescriptor;
import org.apache.polygene.api.entity.EntityDescriptor;
import org.apache.polygene.api.object.ObjectDescriptor;
import org.apache.polygene.api.service.ServiceDescriptor;
import org.apache.polygene.api.value.ValueDescriptor;
import org.apache.polygene.envisage.util.TableRow;
import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.ImportedServiceCompositeDescriptor;
import org.apache.polygene.tools.model.descriptor.ImportedServiceDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;

/**
 * Implementation of General DetailPane
 */
/* package */ final class GeneralPane
    extends DetailPane
{
    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( GeneralPane.class.getName() );

    private JPanel contentPane;
    private JTable table;
    private final GeneralTableModel tableModel;

    /* package */ GeneralPane( DetailModelPane detailModelPane )
    {
        super( detailModelPane );
        this.setLayout( new BorderLayout() );
        this.add( contentPane, BorderLayout.CENTER );

        tableModel = new GeneralTableModel();
        table.setModel( tableModel );

        TableColumnModel columnModel = table.getColumnModel();
        columnModel.getColumn( 0 ).setPreferredWidth( 90 );
        columnModel.getColumn( 1 ).setPreferredWidth( 550 );
    }

    private void clear()
    {
        tableModel.clear();
    }

    @Override
    protected void setDescriptor( Object objectDesciptor )
    {
        clear();
        tableModel.reload( objectDesciptor );
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     */
    private void $$$setupUI$$$()
    {
        contentPane = new JPanel();
        contentPane.setLayout( new BorderLayout( 0, 0 ) );
        final JScrollPane scrollPane1 = new JScrollPane();
        contentPane.add( scrollPane1, BorderLayout.CENTER );
        table = new JTable();
        scrollPane1.setViewportView( table );
    }

    public JComponent $$$getRootComponent$$$()
    {
        return contentPane;
    }

    private static class GeneralTableModel
        extends AbstractTableModel
    {
        /**
         * the column names for this model
         */
        private static final String[] COLUMN_NAMES =
            {
                BUNDLE.getString( "Name.Column" ),
                BUNDLE.getString( "Value.Column" )
            };
        private final ArrayList<TableRow> rows;

        private final String nameRow = "name";
        private final String classRow = "class";
        private final String visibilityRow = "visibility";
        private final String moduleRow = "module";
        private final String layerRow = "layer";

        private GeneralTableModel()
        {
            rows = new ArrayList<>();
        }

        private void reload( Object objectDesciptor )
        {
            if( objectDesciptor instanceof ServiceDetailDescriptor )
            {
                ServiceDescriptor descriptor = ( (ServiceDetailDescriptor) objectDesciptor ).descriptor();
                Class<?> type = descriptor.types().findFirst().get();
                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, type.getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (ServiceDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (ServiceDetailDescriptor) objectDesciptor ).module().layer() ) );
                rows.add( new TableRow( 2, "startup", ( (ServiceDetailDescriptor) objectDesciptor ).descriptor()
                    .isInstantiateOnStartup() ) );
            }
            else if( objectDesciptor instanceof ImportedServiceDetailDescriptor )
            {
                ImportedServiceCompositeDescriptor descriptor = ( (ImportedServiceDetailDescriptor) objectDesciptor ).descriptor();
                rows.add( new TableRow( 2, nameRow, descriptor.primaryType().getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, descriptor.primaryType().getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module()
                    .layer() ) );
            }
            else if( objectDesciptor instanceof EntityDetailDescriptor )
            {
                EntityDescriptor descriptor = ( (EntityDetailDescriptor) objectDesciptor ).descriptor();
                Class<?> type = descriptor.types().findFirst().orElse( null );
                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, type.getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (EntityDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (EntityDetailDescriptor) objectDesciptor ).module().layer() ) );
            }
            else if( objectDesciptor instanceof ValueDetailDescriptor )
            {
                ValueDescriptor descriptor = ( (ValueDetailDescriptor) objectDesciptor ).descriptor();
                Class<?> type = descriptor.types().findFirst().orElse( null );
                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, type.getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (ValueDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (ValueDetailDescriptor) objectDesciptor ).module().layer() ) );
            }
            else if( objectDesciptor instanceof ObjectDetailDescriptor )
            {
                ObjectDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor ).descriptor();
                Class<?> type = descriptor.types().findFirst().orElse( null );
                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, type.getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (ObjectDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (ObjectDetailDescriptor) objectDesciptor ).module().layer() ) );
            }
            else if( objectDesciptor instanceof TransientDetailDescriptor )
            {
                CompositeDescriptor descriptor = ( (TransientDetailDescriptor) objectDesciptor ).descriptor();
                Class<?> type = descriptor.types().findFirst().orElse( null );
                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
                rows.add( new TableRow( 2, classRow, type.getName() ) );
                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
                rows.add( new TableRow( 2, moduleRow, ( (TransientDetailDescriptor) objectDesciptor ).module() ) );
                rows.add( new TableRow( 2, layerRow, ( (TransientDetailDescriptor) objectDesciptor ).module()
                    .layer() ) );
            }

            fireTableDataChanged();
        }

        @Override
        public Object getValueAt( int rowIndex, int columnIndex )
        {
            TableRow row = this.rows.get( rowIndex );
            return row.get( columnIndex );
        }

        private void clear()
        {
            rows.clear();
            fireTableDataChanged();
        }

        @Override
        public int getColumnCount()
        {
            return COLUMN_NAMES.length;
        }

        @Override
        public String getColumnName( int col )
        {
            return COLUMN_NAMES[ col ];
        }

        @Override
        public int getRowCount()
        {
            return rows.size();
        }
    }
}
