/**************************************************************************
 OmegaT - Computer Assisted Translation (CAT) tool 
          with fuzzy matching, translation memory, keyword search, 
          glossaries, and translation leveraging into updated projects.

 Copyright (C) 2018-2021 Thomas Cordonnier
               Home page: http://www.omegat.org/
               Support center: http://groups.yahoo.com/group/OmegaT/

 This file is part of OmegaT.

 OmegaT is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 OmegaT 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 for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/

package org.omegat.core.segmentation;

import java.io.File;
import java.util.List;

import org.omegat.util.Language;
import org.omegat.util.Log;

/**
 * Interface to anything which can be used to build a segmenter
 * 
 * @author Thomas Cordonnier
 */
public interface ISegmentationData {
	
    /**
     * Finds the rules for a certain language.
     * <p>
     * Usually (if the user didn't screw up the setup) there're a default
     * segmentation rules, so it's a good idea to rely on this method always
     * returning at least some rules.
     * <p>
     * Or in case of a completely screwed setup -- an empty list without any
     * rules.
     */
    public abstract List<Rule> lookupRulesForLanguage(Language srclang);

	/**
	 * For the moment we can edit only SRX,
	 * so if the user wants to edit we will convert to SRX
	 * (any format should be convertible, eventually loosing info)
	 **/
	public SRX toSRX();

    // --------------------------------- Factories ----------------------------------------
    
    public static final String CONF_SENTSEG = "segmentation.conf";
    public static final String SRX_SENTSEG = "segmentation.srx";	
    public static final String CSCX_SENTSEG = "segmentation.cscx";	
	
    /**
     * Loads the local segmentation file. Accepts CSCX (default), SRX or old CONF format.
     * Accepts -2srx.conf or -2conf.srx, in which case it also tries to convert to other format.
     * In case you use conf format, rules about old version remain valid.
     *
     * @param configDir		The directory to search in. Not the file, because here we will search for various formats
     * @param fallbackDefault		When the file is not found, return default if true. Else return null
     **/
    public static ISegmentationData loadFromDir(File configDir, boolean fallbackDefault) {
        // If CSC exists, load it and eventually convert it. Conversion <em>to</em> CSC is not supported.
	File inFile = new File (configDir, CSCX_SENTSEG.replace(".","-2conf."));
        if (inFile.exists()) 
            try {
                ISegmentationData res = CSC.loadCscxFile(inFile.toURL()); 
                try { SRX.saveToConf(res.toSRX(), new File (configDir,CONF_SENTSEG)); inFile.delete(); } catch (Exception i1) { Log.log(i1); /* could not convert, but could read */ } 
                return res; 
            } catch (Exception o1) {
		Log.log(o1);
            }
	inFile = new File (configDir, CSCX_SENTSEG.replace(".","-2srx."));
        if (inFile.exists()) 
            try { 
                ISegmentationData res = CSC.loadCscxFile(inFile.toURL()); 
                try { SRX.saveToSrx(res.toSRX(), new File (configDir,SRX_SENTSEG)); inFile.delete(); } catch (Exception i1) { Log.log(i1); /* could not convert, but could read */ } 
                return res; 
            } catch (Exception o2) {
		Log.log(o2);
            }
	inFile = new File (configDir, CSCX_SENTSEG);
	if (inFile.exists()) try { return CSC.loadCscxFile(inFile.toURL()); } catch (Exception o2) { Log.log(o2); }
		
	// Load SRX, then CONF if not exists. Eventually do a conversion
        inFile = new File (configDir, SRX_SENTSEG.replace(".","-2conf."));
        if (inFile.exists()) 
            try { 
                SRX res = SRX.loadSrxFile(inFile.toURL()); 
                try { SRX.saveToConf(res, new File (configDir,CONF_SENTSEG)); inFile.delete(); } catch (Exception i1) { Log.log(i1); /* could not convert, but could read */ } 
                return res; 
            } catch (Exception o5) {
            }				
        inFile = new File (configDir, CONF_SENTSEG.replace(".","-2srx."));
        if (inFile.exists()) { 
            SRX res = SRX.loadConfFile(inFile); 
            try { inFile.delete(); SRX.saveToSrx(res, new File (configDir,SRX_SENTSEG)); } catch (Exception i2) { Log.log(i2); /* could not convert, but could read */ } 
            return res; 
        } 
        inFile = new File (configDir, CONF_SENTSEG);
        if (inFile.exists()) return SRX.loadConfFile(inFile);
        else { 
            inFile = new File (configDir, SRX_SENTSEG); 
            if (inFile.exists()) try { return SRX.loadSrxFile(inFile.toURL()); } catch (Exception o8) {}
            
            // Note: as in previous version (3.6) return a new SRX with defaults
            return fallbackDefault ? ISegmentationData.getDefault() : null;
        }
    }
    
    /**
     * Saves segmentation rules into specified directory.
     * Applies rules from SRX except if the file is not an SRX
     */
    public static void saveTo(ISegmentationData data, File outDir) throws java.io.IOException {
        if (data == null) SRX.saveTo(null, outDir); // delete
        if (data instanceof SRX) SRX.saveTo((SRX) data, outDir);
        if (data instanceof CSC) CSC.saveTo((CSC) data, new File(outDir, CSCX_SENTSEG));
    }
    
        
    /**
     * Does a config file already exists for the project at the given location?
     * @param configDir the project directory for storage of settings file
     */
    public static boolean projectConfigFileExists(String configDir) {
        File configFile = new File(configDir + CONF_SENTSEG);
        return configFile.exists();
    }

    /**
     * Initializes default rules. Actually in SRX format, but may change.
     */
    public static SRX getDefault() {
        SRX srx = SRX.loadSrxFile(SRX.class.getResource("defaultRules.srx"));
        /*srx.includeEndingTags=true;
        srx.segmentSubflows=true;*/
        return srx;
    }	
    
    public boolean isCascade();
    public boolean isIncludeStartingTags();
    public boolean isIncludeEndingTags();
    public boolean isIncludeIsolatedTags();
    
    /**
     * Returns all mapping rules (of class {@link MapRule}) at once:
     * correspondences between languages and their segmentation rules.
     */
    public List<MapRule> getMappingRules();	
    
    /** Insert a new mapRule. Do not use getMappingRules().add(...), this may not update some internal fields **/
    public void insertMapRule(int pos, MapRule mr);
    
    /** Insert a new rule. Do not use mappingRule.getRules().add(...), this may not update some internal fields **/
    public void insertRule(int pos, MapRule mr, Rule r);
}
