package ca.janeg.cb;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;

/**
 *  A component to display formatted text detailing the superclasses,
 *  interfaces, fields, constructor, and methods of a selected class.
 *
 *  @author     Jane Griscti jane@janeg.ca
 *  @created    January 5, 2002
 */
class CBTextPane extends JTextPane {
    CBClassInfo currentClass;
    CBDocument doc;


    /**  Construct a new CBTextPane object */
    CBTextPane() {
        super();
    }


    /**
     *  Formats the class name and assigns it to the first line of the display
     *  document.
     */
    private void showHeading() {
        String head  = null;

        if( currentClass.isInterface() ) {
            head = "Details for Interface " + currentClass.getFullyQualifiedName();
        } else {
            head = "Details for Class " + currentClass.getFullyQualifiedName();
        }

        try {
            AttributeSet s  = doc.getStyle( doc.HEADING );
            doc.insertString( doc.getLength(),
                head + "\n",
                s );
            doc.setLogicalStyle( doc.getLength() - 1, (Style)s );
        } catch( BadLocationException e ) {
            JOptionPane.showMessageDialog( this,
                "Error displaying details. /n" + e,
                "Display Error",
                JOptionPane.ERROR_MESSAGE );
            return;
        }
    }


    /**
     *  Retreives the class superclasses, formats their names and adds them to
     *  the display document
     */
    private void showSuperClasses() {
        String[] supers  = currentClass.getSuperClasses();

        if( supers == null ) {
            return;
        }

        AttributeSet s   = doc.getStyle( doc.HEADING );
        try {
            doc.insertString( doc.getLength(),
                "SuperClasses \n",
                s );
        } catch( BadLocationException e ) {
            JOptionPane.showMessageDialog( this,
                "Error displaying details. /n" + e,
                "Display Error",
                JOptionPane.ERROR_MESSAGE );
            return;
        }

        doc.setLogicalStyle( doc.getLength() - 1, (Style)s );

        for( int i = 0; i < supers.length; i++ ) {

            try {
                doc.insertString( doc.getLength(),
                    supers[i] + "\n",
                    doc.getStyle( doc.BASIC ) );
            } catch( BadLocationException e ) {
                JOptionPane.showMessageDialog( this,
                    "Error displaying details. /n" + e,
                    "Display Error",
                    JOptionPane.ERROR_MESSAGE );
                return;
            }
        }
    }


    /**
     *  Formats the class details and adds them to the display document.
     *
     *@param  data  An array of Interface, Field, Constructor, or Method objects
     *@param  type  Description of Parameter
     */
    private void showData( final Object[] data, final String type ) {

        if( data == null ) {
            return;
        }

        try {
            if( type != "" ) {
                AttributeSet s  = doc.getStyle( doc.HEADING );
                doc.insertString( doc.getLength(),
                    type + "\n",
                    s );
                doc.setLogicalStyle( doc.getLength() - 1, (Style)s );
            }else{
                doc.insertString( doc.getLength(),
                                  "\n",
                                  doc.getStyle( doc.BASIC ) );
            }

            for( int i = 0; i < data.length; i++ ) {
                displayLine( data[i].toString() );
                doc.insertString( doc.getLength(),
                    "\n",
                    doc.getStyle( doc.BASIC ) );
            }
        } catch( BadLocationException e ) {
            JOptionPane.showMessageDialog( this,
                "Error displaying details. /n" + e,
                "Display Error",
                JOptionPane.ERROR_MESSAGE );
            return;
        }
    }


    /**
     *  Write a new line in the document
     *
     *  @param  line  the text to be displayed
     */
    private void displayLine( final String line ) {
        String className      = currentClass.getSimpleName();
        StringTokenizer stok  = new StringTokenizer( line, " (", true );
        String token          = new String( "" );

        while( stok.hasMoreTokens() ) {
            token = stok.nextToken();

            try {
                if( token.indexOf( className ) == -1 ) {
                    if( token.lastIndexOf( '.' ) > 0 &&
                        !token.endsWith( ")" ) ) {
                            int pos  = token.lastIndexOf( '.' );
                            token = token.substring( pos + 1 );
                    }

                    doc.insertString( doc.getLength(),
                        token,
                        doc.getStyle( doc.BASIC ) );
                } else {
                    // show field, method, ctor name in bold
                    int pos  = token.lastIndexOf( '.' );
                    doc.insertString( doc.getLength(),
                        token.substring( pos + 1 ),
                        doc.getStyle( doc.BOLD ) );
                }
            } catch( BadLocationException e ) {
                JOptionPane.showMessageDialog( this,
                    "Error displaying details. /n" + e,
                    "Display Error",
                    JOptionPane.ERROR_MESSAGE );
                return;
            }
        }

    }


    /**
     *  Replaces the current content with the details of the supplied class. All
     *  content is displayed using a StyledDocument.
     *
     *@param  str  the name of the class for which details will be displayed
     */
    void displayClassInfo( final String str ) {

        try {
            currentClass = new CBClassInfo( str );
        } catch( ClassNotFoundException e ) {
            JOptionPane.showMessageDialog( this,
                "Unable to load class " + str +
                "\nPlease check your classpath.",
                "Error Loading Class",
                JOptionPane.ERROR_MESSAGE );
            return;
        }

        doc = new CBDocument();
        setStyledDocument( doc );

        showHeading();

        if( currentClass.hasSuperClasses() ) {
            showSuperClasses();
            Class[] inter        = currentClass.getMemberInterfaces();
            showData( inter, "Interfaces" );
        }

        Class[] members      = currentClass.getMemberClasses();
        showData( members, "Member Classes");

        if( currentClass.hasFields() ) {
            Field[] flds         = currentClass.getPublicFields();
            showData( flds, "Fields" );
            flds                 = currentClass.getPackageFields();
            showData( flds, "" );
            flds                 = currentClass.getProtectedFields();
            showData( flds, "" );
            flds                 = currentClass.getPrivateFields();
            showData( flds, "" );
        }

        if( currentClass.hasCtors() ) {
            Constructor[] ctors  = currentClass.getPublicConstructors();
            showData( ctors, "Constructors" );
            ctors  = currentClass.getProtectedConstructors();
            showData( ctors, "" );
            ctors  = currentClass.getPackageConstructors();
            showData( ctors, "" );
            ctors  = currentClass.getPrivateConstructors();
            showData( ctors, "" );
        }

        if( currentClass.hasMethods() ) {
            Method[] methods     = currentClass.getPublicMethods();
            showData( methods, "Methods" );
            methods     = currentClass.getProtectedMethods();
            showData( methods, "" );
            methods     = currentClass.getPackageMethods();
            showData( methods, "" );
            methods     = currentClass.getPrivateMethods();
            showData( methods, "" );
        }
        setCaretPosition( 0 );
    }
}