/*
 * Created on 2004-08-17
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2004
 */
package pl.zalewski.mikolaj.symbdev;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.resources.ScannerProvider;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;

import pl.zalewski.mikolaj.symbdev.properties.ProjectProperties;

/**
 * @author mikolaj
 *
 * This class provides the include paths for the C++ scanner. They are
 * generated from the EPOCROOT and the MMP files
 * 
 * TODO load the include paths from the MMP files
 * 
 * @deprecated Adding paths in SymbianPrjNature.applyPaths seems to
 * work better
 */
public class SymbianScannerProvider extends ScannerProvider
{
    static final String SCANNER_ID=SymbdevPlugin.getUniqueIdentifier()+".SymbianScannerProvider"; 
    
    public SymbianScannerProvider()
    {
    }

	public static SymbianScannerProvider getDefault() {
        if (defaultProvider == null) {
			defaultProvider = new SymbianScannerProvider();
		}
		return defaultProvider;
	}
	
	public IScannerInfo getScannerInformation(IResource resource) {
	    IScannerInfo info;
	    
		try {
		    IProject prj=resource.getProject();
		    if (!prj.hasNature("pl.zalewski.mikolaj.symbdev.symbianPrjNature"))
		        return super.getScannerInformation(resource);
		    System.out.println("getSymbianScannerInfo...");
			info=getSymbianScannerInfo(prj, true);
			return info;
		} catch (CoreException e) {
		    e.printStackTrace();
		}
		return super.getScannerInformation(resource);
	}

    protected SymbianScannerInfo getSymbianScannerInfo(IProject project, boolean b)
    	throws CoreException
    {
        SymbianScannerInfo info=new SymbianScannerInfo();
        String[] includePaths=new String[2];
        includePaths[0]=new Path(ProjectProperties.getSymbianSDK(project).epocRoot).append("epoc32/include").toString();
        
        IPath prjPath=project.getLocation();
        Path p=new Path(ProjectProperties.getIncPath(project));
        includePaths[1]=prjPath.append(p).toString();
        info.setIncludePaths(includePaths);
        
        String[] defines=null;
        defines=getPlatformDefines(project);
        
        HashMap m=new HashMap();
        for (int i=0; i<defines.length; i++)
            m.put(defines[i], "");
        info.setDefinedSymbols(m);
        
        return info;
    }
    
    public static void addToProject(IProject project)
    	throws CoreException
    {
		ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(project, true);
		desc.create(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID, SCANNER_ID);        
    }
    
    public static String[] getPlatformDefines(IProject project)
    	throws CoreException
    {
        SymbianSDKEntry sdk=ProjectProperties.getSymbianSDK(project);
        Win32ToolEntry tool=ProjectProperties.getWin32Tool(project);
        if (cachedMacros!=null)
        {
            if (cachedForSDK==sdk && cachedForEntry==tool)
                return cachedMacros;
        }
        
        cachedMacros=getPlatformDefinesFromBldmake(project);
        cachedForEntry=tool;
        cachedForSDK=sdk;
        return cachedMacros;
    }
    
    static String[] cachedMacros;
    static Win32ToolEntry cachedForEntry;
    static SymbianSDKEntry cachedForSDK;
    
    
    protected static String[] getPlatformDefinesFromBldmake(IProject project)
    	throws CoreException
    {
        System.out.println("Querying bldmake for platform macros.");
        
        SymbianCommandLauncher launcher=new SymbianCommandLauncher();
        String[] args=new String[2];
        args[0]="plat";
        args[1]=ProjectProperties.getWin32Tool(project).target;
        Process p=launcher.execute(project, "bldmake", args);
		try {
			// Close the input of the Process explicitely.
			// We will never write to it.
			p.getOutputStream().close();
		} catch (IOException e) {
		}
		
		InputStream output=p.getInputStream();
		InputStreamReader reader=new InputStreamReader(output);
		BufferedReader buf=new BufferedReader(reader);
		
		// the last line contains the macros
		String line=null;
		String prevLine;
		do {
		    prevLine=line;
		    try {
		        line=buf.readLine();
		    }
		    catch (IOException e)
		    {
		        e.printStackTrace();
		        return null;
		    }
		} while (line!=null);
		
		if (prevLine==null)
		    return new String[0];
		line=prevLine;
		line=line.replaceAll("\\s+", " ");
		line=line.trim();
		String[] macros=line.split(" ");
        
        return macros;
    }

    static SymbianScannerProvider defaultProvider;
}
