/*
 * Copyright (c) 1998, 2008, 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.tools.example.debug.gui;

import java.io.*;
import java.util.*;

import com.sun.jdi.*;
import com.sun.jdi.request.*;

import com.sun.tools.example.debug.bdi.*;

import javax.swing.*;

/**
 * Represents and manages one source file.
 * Caches source lines.  Holds other source file info.
 */
public class SourceModel extends AbstractListModel {

    private File path;

    boolean isActuallySource = true;

    private List<ReferenceType> classes = new ArrayList<ReferenceType>();

    private Environment env;

    // Cached line-by-line access.

    //### Unify this with source model used in source view?
    //### What is our cache-management policy for these?
    //### Even with weak refs, we won't discard any part of the
    //### source if the SourceModel object is reachable.
    /**
     * List of Line.
     */
    private List<Line> sourceLines = null;

    public static class Line {
        public String text;
        public boolean hasBreakpoint = false;
        public ReferenceType refType = null;
        Line(String text) {
            this.text = text;
        }
        public boolean isExecutable() {
            return refType != null;
        }
        public boolean hasBreakpoint() {
            return hasBreakpoint;
        }
    };

    // 132 characters long, all printable characters.
    public static final Line prototypeCellValue = new Line(
                                        "abcdefghijklmnopqrstuvwxyz" +
                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                                        "1234567890~!@#$%^&*()_+{}|" +
                                        ":<>?`-=[];',.XXXXXXXXXXXX/\\\"");

    SourceModel(Environment env, File path) {
        this.env = env;
        this.path = path;
    }

    public SourceModel(String message) {
        this.path = null;
        setMessage(message);
    }

    private void setMessage(String message) {
        isActuallySource = false;
        sourceLines = new ArrayList<Line>();
        sourceLines.add(new Line(message));
    }

    // **** Implement ListModel  *****

    public Object getElementAt(int index) {
        if (sourceLines == null) {
            initialize();
        }
        return sourceLines.get(index);
    }

    public int getSize() {
        if (sourceLines == null) {
            initialize();
        }
        return sourceLines.size();
    }

    // ***** Other functionality *****

    public File fileName() {
        return path;
    }

    public BufferedReader sourceReader() throws IOException {
        return new BufferedReader(new FileReader(path));
    }

    public Line line(int lineNo) {
        if (sourceLines == null) {
            initialize();
        }
        int index = lineNo - 1; // list is 0-indexed
        if (index >= sourceLines.size() || index < 0) {
            return null;
        } else {
            return sourceLines.get(index);
        }
    }

    public String sourceLine(int lineNo) {
        Line line = line(lineNo);
        if (line == null) {
            return null;
        } else {
            return line.text;
        }
    }

    void addClass(ReferenceType refType) {
        // Logically is Set
        if (classes.indexOf(refType) == -1) {
            classes.add(refType);
            if (sourceLines != null) {
                markClassLines(refType);
            }
        }
    }

    /**
     * @return List of currently known {@link com.sun.jdi.ReferenceType}
     * in this source file.
     */
    public List<ReferenceType> referenceTypes() {
        return Collections.unmodifiableList(classes);
    }

    private void initialize() {
        try {
            rawInit();
        } catch (IOException exc) {
            setMessage("[Error reading source code]");
        }
    }

    public void showBreakpoint(int ln, boolean hasBreakpoint) {
        line(ln).hasBreakpoint = hasBreakpoint;
        fireContentsChanged(this, ln, ln);
    }

    public void showExecutable(int ln, ReferenceType refType) {
        line(ln).refType = refType;
        fireContentsChanged(this, ln, ln);
    }

    /**
     * Mark executable lines and breakpoints, but only
     * when sourceLines is set.
     */
    private void markClassLines(ReferenceType refType) {
        for (Method meth : refType.methods()) {
            try {
                for (Location loc : meth.allLineLocations()) {
                    showExecutable(loc.lineNumber(), refType);
                }
            } catch (AbsentInformationException exc) {
                // do nothing
            }
        }
        for (BreakpointRequest bp :
                 env.getExecutionManager().eventRequestManager().breakpointRequests()) {
            if (bp.location() != null) {
                Location loc = bp.location();
                if (loc.declaringType().equals(refType)) {
                    showBreakpoint(loc.lineNumber(),true);
                }
            }
        }
    }

    private void rawInit() throws IOException {
        sourceLines = new ArrayList<Line>();
        BufferedReader reader = sourceReader();
        try {
            String line = reader.readLine();
            while (line != null) {
                sourceLines.add(new Line(expandTabs(line)));
                line = reader.readLine();
            }
        } finally {
            reader.close();
        }
        for (ReferenceType refType : classes) {
            markClassLines(refType);
        }
    }

    private String expandTabs(String s) {
        int col = 0;
        int len = s.length();
        StringBuffer sb = new StringBuffer(132);
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            sb.append(c);
            if (c == '\t') {
                int pad = (8 - (col % 8));
                for (int j = 0; j < pad; j++) {
                    sb.append(' ');
                }
                col += pad;
            } else {
                col++;
            }
        }
        return sb.toString();
    }

}
