/*******************************************************************************
 * Copyright (c) 2016 ModelSolv, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    ModelSolv, Inc. - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.reprezen.swagedit.core.quickfix;

import static com.reprezen.swagedit.core.preferences.KaiZenPreferencesUtils.getTabWidth;

import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.osgi.framework.Bundle;

import com.reprezen.swagedit.core.validation.Messages;

public class QuickFixer implements IMarkerResolutionGenerator2 {

    @Override
    public IMarkerResolution[] getResolutions(IMarker marker) {
        if (isMissingObjectType(marker)) {
            return new IMarkerResolution[] { new FixMissingObjectType() };
        }
        return new IMarkerResolution[0];
    }

    @Override
    public boolean hasResolutions(IMarker marker) {
        return isMissingObjectType(marker);
    }

    private boolean isMissingObjectType(IMarker marker) {
        try {
            return Messages.error_object_type_missing.equals(marker.getAttribute(IMarker.MESSAGE));
        } catch (CoreException e) {
            return false;
        }
    }

    public static class FixMissingObjectType extends TextDocumentMarkerResolution {
        private static final Pattern WHITESPACE_PATTERN = Pattern.compile("(\\s+)\\S.*", Pattern.DOTALL);

        public String getLabel() {
            return "Set schema definition to object type";
        }

        @Override
        public String getDescription() {
            return null;
        }

        @Override
        public Image getImage() {
            Bundle bundle = Platform.getBundle("org.eclipse.ui.editors");
            URL url = FileLocator.find(bundle, new Path("icons/full/obj16/quick_fix_warning_obj.png"), null);
            ImageDescriptor imageDesc = ImageDescriptor.createFromURL(url);
            Image image = imageDesc.createImage();
            return image;
        }

        @Override
        public IRegion processFix(IDocument document, IMarker marker) throws CoreException {
            int line = (int) marker.getAttribute(IMarker.LINE_NUMBER);
            try {
                String indent = getIndent(document, line);
                // getLineOffset() is zero-based, and imarkerLine is one-based.
                int endOfCurrLine = document.getLineInformation(line - 1).getOffset()
                        + document.getLineInformation(line - 1).getLength();
                // should be fine for first and last lines in the doc as well
                String replacementText = indent + "type: object";
                String delim = TextUtilities.getDefaultLineDelimiter(document);
                document.replace(endOfCurrLine, 0, delim + replacementText);
                return new Region(endOfCurrLine + delim.length(), replacementText.length());
            } catch (BadLocationException e) {
                throw new CoreException(createStatus(e, "Cannot process the IMarker"));
            }
        }

        protected String getIndent(IDocument document, int line) throws BadLocationException {
            String definitionLine = document.get(document.getLineOffset(line - 1), document.getLineLength(line - 1));
            Matcher m = WHITESPACE_PATTERN.matcher(definitionLine);
            final String definitionIndent = m.matches() ? m.group(1) : "";
            StringBuilder indent = new StringBuilder();
            indent.append(definitionIndent);
            IntStream.range(0, getTabWidth()).forEach(el -> indent.append(" "));
            return indent.toString();
        }

    }

}