/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/


package org.apache.james.jspf.core;

/**
 * This Class is used to convert all macros which can used in SPF-Records to the
 * right values!
 * 
 */

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.james.jspf.core.exceptions.NeutralException;
import org.apache.james.jspf.core.exceptions.NoneException;
import org.apache.james.jspf.core.exceptions.PermErrorException;
import org.apache.james.jspf.core.exceptions.TempErrorException;
import org.apache.james.jspf.core.exceptions.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MacroExpand {
    private static final Logger LOGGER = LoggerFactory.getLogger(MacroExpand.class);

    private Pattern domainSpecPattern;

    private Pattern macroStringPattern;

    private Pattern macroLettersPattern;

    private Pattern macroLettersExpPattern;

    private Pattern cellPattern;

    private DNSService dnsProbe;

    public static final boolean EXPLANATION = true;
    
    public static final boolean DOMAIN = false;
    
    public static class RequireClientDomainException extends Exception {

        private static final long serialVersionUID = 3834282981657676530L;
        
    }

    /**
     * Construct MacroExpand
     * 
     * @param dnsProbe the dns service to use
     */
    public MacroExpand(DNSService dnsProbe) {
        // This matches 2 groups
        domainSpecPattern = Pattern.compile(SPFTermsRegexps.DOMAIN_SPEC_REGEX_R);
        // The real pattern replacer
        macroStringPattern = Pattern.compile(SPFTermsRegexps.MACRO_STRING_REGEX_TOKEN);
        // The macro letters pattern
        macroLettersExpPattern = Pattern.compile(SPFTermsRegexps.MACRO_LETTER_PATTERN_EXP);
        macroLettersPattern = Pattern.compile(SPFTermsRegexps.MACRO_LETTER_PATTERN);
        this.dnsProbe = dnsProbe;
    }
    

    private static final class AResponseListener implements
            SPFCheckerDNSResponseListener {
        
        /**
         * @see org.apache.james.jspf.core.SPFCheckerDNSResponseListener#onDNSResponse(org.apache.james.jspf.core.DNSResponse, org.apache.james.jspf.core.SPFSession)
         */
        public DNSLookupContinuation onDNSResponse(DNSResponse response, SPFSession session)
                throws PermErrorException, NoneException, TempErrorException,
                NeutralException {
            // just return the default "unknown" if we cannot find anything
            // later
            session.setClientDomain("unknown");
            try {
                List<String> records = response.getResponse();
                if (records != null && records.size() > 0) {
                    Iterator<String> i = records.iterator();
                    while (i.hasNext()) {
                        String next = i.next();
                        if (IPAddr.getAddress(session.getIpAddress())
                                .toString().equals(
                                        IPAddr.getAddress(next).toString())) {
                            session
                                    .setClientDomain((String) session
                                            .getAttribute(ATTRIBUTE_MACRO_EXPAND_CHECKED_RECORD));
                            break;
                        }
                    }
                }
            } catch (TimeoutException e) {
                // just return the default "unknown".
            } catch (PermErrorException e) {
                // just return the default "unknown".
            }
            return null;
        }
    }

    private static final class PTRResponseListener implements
            SPFCheckerDNSResponseListener {

        /**
         * @see org.apache.james.jspf.core.SPFCheckerDNSResponseListener#onDNSResponse(org.apache.james.jspf.core.DNSResponse, org.apache.james.jspf.core.SPFSession)
         */
        public DNSLookupContinuation onDNSResponse(DNSResponse response, SPFSession session)
                throws PermErrorException, NoneException, TempErrorException,
                NeutralException {

            try {
                boolean ip6 = IPAddr.isIPV6(session.getIpAddress());
                List<String> records = response.getResponse();

                if (records != null && records.size() > 0) {
                    String record = records.get(0);
                    session.setAttribute(ATTRIBUTE_MACRO_EXPAND_CHECKED_RECORD,
                            record);

                    return new DNSLookupContinuation(new DNSRequest(record,
                            ip6 ? DNSRequest.AAAA : DNSRequest.A), 
                            new AResponseListener());

                }
            } catch (TimeoutException e) {
                // just return the default "unknown".
            }
                    
            session.setClientDomain("unknown");        
            return null;

        }
    }

    private static final String ATTRIBUTE_MACRO_EXPAND_CHECKED_RECORD = "MacroExpand.checkedRecord";

    public DNSLookupContinuation checkExpand(String input, SPFSession session, boolean isExplanation) throws PermErrorException, NoneException {
        if (input != null) {
            String host = this.expand(input, session, isExplanation);
            if (host == null) {

                return new DNSLookupContinuation(new DNSRequest(IPAddr
                        .getAddress(session.getIpAddress()).getReverseIP(),
                        DNSRequest.PTR), new PTRResponseListener());
            }
        }
        return null;
    }
    
    public String expand(String input, MacroData macroData, boolean isExplanation) throws PermErrorException {
        try {
            if (isExplanation) {
                return expandExplanation(input, macroData);
            } else {
                return expandDomain(input, macroData);
            }
        } catch (RequireClientDomainException e) {
            return null;
        }
    }

    /**
     * This method expand the given a explanation
     * 
     * @param input
     *            The explanation which should be expanded
     * @return expanded The expanded explanation
     * @throws PermErrorException
     *             Get thrown if invalid macros are used
     * @throws RequireClientDomain 
     */
    private String expandExplanation(String input, MacroData macroData) throws PermErrorException, RequireClientDomainException {

        LOGGER.debug("Start do expand explanation: {}", input);

        String[] parts = input.split(" ");
        StringBuffer res = new StringBuffer();
        for (int i = 0; i < parts.length; i++) {
            if (i > 0) res.append(" ");
            res.append(expandMacroString(parts[i], macroData, true));
        }
        LOGGER.debug("Done expand explanation: {}", res);
        
        return res.toString();
    }

    /**
     * This method expand the given domain. So all known macros get replaced
     * 
     * @param input
     *            The domain which should be expand
     * @return expanded The domain with replaced macros
     * @throws PermErrorException
     *             This get thrown if invalid macros are used
     * @throws RequireClientDomain 
     */
    private String expandDomain(String input, MacroData macroData) throws PermErrorException, RequireClientDomainException {

        LOGGER.debug("Start expand domain: {}", input);

        Matcher inputMatcher = domainSpecPattern.matcher(input);
        if (!inputMatcher.matches() || inputMatcher.groupCount() != 2) {
            throw new PermErrorException("Invalid DomainSpec: "+input);
        }

        StringBuffer res = new StringBuffer();
        if (inputMatcher.group(1) != null && inputMatcher.group(1).length() > 0) {
            res.append(expandMacroString(inputMatcher.group(1), macroData, false));
        }
        if (inputMatcher.group(2) != null && inputMatcher.group(2).length() > 0) {
            if (inputMatcher.group(2).startsWith(".")) {
                res.append(inputMatcher.group(2));
            } else {
                res.append(expandMacroString(inputMatcher.group(2), macroData, false));
            }
        }
        
        String domainName = expandMacroString(input, macroData, false);
        // reduce to less than 255 characters, deleting subdomains from left
        int split = 0;
        while (domainName.length() > 255 && split > -1) {
            split = domainName.indexOf(".");
            domainName = domainName.substring(split + 1);
        }

        LOGGER.debug("Domain expanded: {}", domainName);
        
        return domainName;
    }

    /**
     * Expand the given String
     * 
     * @param input
     *            The inputString which should get expanded
     * @return expanded The expanded given String
     * @throws PermErrorException
     *             This get thrown if invalid macros are used
     * @throws RequireClientDomain 
     */
    private String expandMacroString(String input, MacroData macroData, boolean isExplanation) throws PermErrorException, RequireClientDomainException {

        StringBuffer decodedValue = new StringBuffer();
        Matcher inputMatcher = macroStringPattern.matcher(input);
        String macroCell;
        int pos = 0;

        while (inputMatcher.find()) {
            String match2 = inputMatcher.group();
            if (pos != inputMatcher.start()) {
                throw new PermErrorException("Middle part does not match: "+input.substring(0,pos)+">>"+input.substring(pos, inputMatcher.start())+"<<"+input.substring(inputMatcher.start())+" ["+input+"]");
            }
            if (match2.length() > 0) {
                if (match2.startsWith("%{")) {
                    macroCell = input.substring(inputMatcher.start() + 2, inputMatcher
                            .end() - 1);
                    inputMatcher
                            .appendReplacement(decodedValue, escapeForMatcher(replaceCell(macroCell, macroData, isExplanation)));
                } else if (match2.length() == 2 && match2.startsWith("%")) {
                    // handle the % escaping
                    /*
                     * From RFC4408:
                     * 
                     * A literal "%" is expressed by "%%".
                     *   "%_" expands to a single " " space.
                     *   "%-" expands to a URL-encoded space, viz., "%20".
                     */
                    if ("%_".equals(match2)) {
                        inputMatcher.appendReplacement(decodedValue, " ");
                    } else if ("%-".equals(match2)) {
                        inputMatcher.appendReplacement(decodedValue, "%20");
                    } else {
                        inputMatcher.appendReplacement(decodedValue, escapeForMatcher(match2.substring(1)));
                    }
                }
            }
            
            pos = inputMatcher.end();
        }
        
        if (input.length() != pos) {
            throw new PermErrorException("End part does not match: "+input.substring(pos));
        }
        
        inputMatcher.appendTail(decodedValue);

        return decodedValue.toString();
    }

    /**
     * Replace the macros in given String
     * 
     * @param replaceValue
     *            The String in which known macros should get replaced
     * @return returnData The String with replaced macros
     * @throws PermErrorException
     *             Get thrown if an error in processing happen
     * @throws RequireClientDomain 
     */
    private String replaceCell(String replaceValue, MacroData macroData, boolean isExplanation) throws PermErrorException, RequireClientDomainException {

        String variable = "";
        String domainNumber = "";
        boolean isReversed = false;
        String delimeters = ".";

        
        // Get only command character so that 'r' command and 'r' modifier don't
        // clash
        String commandCharacter = replaceValue.substring(0, 1);
        Matcher cellMatcher;
        // Find command
        if (isExplanation) {
            cellMatcher = macroLettersExpPattern.matcher(commandCharacter);
        } else {
            cellMatcher = macroLettersPattern.matcher(commandCharacter);
        }
        if (cellMatcher.find()) {
            if (cellMatcher.group().toUpperCase().equals(cellMatcher.group())) {
                variable = encodeURL(matchMacro(cellMatcher.group(), macroData));
            } else {
                variable = matchMacro(cellMatcher.group(), macroData);
            }
            // Remove Macro code so that r macro code does not clash with r the
            // reverse modifier
            replaceValue = replaceValue.substring(1);
        } else {
            throw new PermErrorException("MacroLetter not found: "+replaceValue);
        }

        // Find number of domains to use
        cellPattern = Pattern.compile("\\d+");
        cellMatcher = cellPattern.matcher(replaceValue);
        while (cellMatcher.find()) {
            domainNumber = cellMatcher.group();
            if (Integer.parseInt(domainNumber) == 0) {
                throw new PermErrorException(
                        "Digit transformer must be non-zero");
            }
        }
        // find if reversed
        cellPattern = Pattern.compile("r");
        cellMatcher = cellPattern.matcher(replaceValue);
        while (cellMatcher.find()) {
            isReversed = true;
        }

        // find delimeters
        cellPattern = Pattern.compile("[\\.\\-\\+\\,\\/\\_\\=]+");
        cellMatcher = cellPattern.matcher(replaceValue);
        while (cellMatcher.find()) {
            delimeters = cellMatcher.group();
        }

        // Reverse domains as necessary
        ArrayList<String> data = split(variable, delimeters);
        if (isReversed) {
            data = reverse(data);
        }

        // Truncate domain name to number of sub sections
        String returnData;
        if (!domainNumber.equals("")) {
            returnData = subset(data, Integer.parseInt(domainNumber));
        } else {
            returnData = subset(data);
        }

        return returnData;

    }

    /**
     * Get the value for the given macro like descripted in the RFC
     * 
     * @param macro
     *            The macro we want to get the value for
     * @return rValue The value for the given macro
     * @throws PermErrorException
     *             Get thrown if the given variable is an unknown macro
     * @throws RequireClientDomain requireClientDomain if the client domain is needed
     *             and not yet resolved.
     */
    private String matchMacro(String macro, MacroData macroData) throws PermErrorException, RequireClientDomainException {

        String rValue = null;

        String variable = macro.toLowerCase();
        if (variable.equalsIgnoreCase("i")) {
            rValue = macroData.getMacroIpAddress();
        } else if (variable.equalsIgnoreCase("s")) {
            rValue = macroData.getMailFrom();
        } else if (variable.equalsIgnoreCase("h")) {
            rValue = macroData.getHostName();
        } else if (variable.equalsIgnoreCase("l")) {
            rValue = macroData.getCurrentSenderPart();
        } else if (variable.equalsIgnoreCase("d")) {
            rValue = macroData.getCurrentDomain();
        } else if (variable.equalsIgnoreCase("v")) {
            rValue = macroData.getInAddress();
        } else if (variable.equalsIgnoreCase("t")) {
            rValue = Long.toString(macroData.getTimeStamp());
        } else if (variable.equalsIgnoreCase("c")) {
            rValue = macroData.getReadableIP();
        } else if (variable.equalsIgnoreCase("p")) {
            rValue = macroData.getClientDomain();
            if (rValue == null) {
                throw new RequireClientDomainException();
            }
        } else if (variable.equalsIgnoreCase("o")) {
            rValue = macroData.getSenderDomain();
        } else if (variable.equalsIgnoreCase("r")) {
            rValue = macroData.getReceivingDomain();
            if (rValue == null) {
                rValue = "unknown";
                List<String> dNames = dnsProbe.getLocalDomainNames();

                for (int i = 0; i < dNames.size(); i++) {
                    // check if the domainname is a FQDN
                    if (SPF1Utils.checkFQDN(dNames.get(i).toString())) {
                        rValue = dNames.get(i).toString();
                        if (macroData instanceof SPFSession) {
                            ((SPFSession) macroData).setReceivingDomain(rValue);
                        }
                        break;
                    }
                }
            }
        }

        if (rValue == null) {
            throw new PermErrorException("Unknown command : " + variable);

        } else {
            LOGGER.debug("Used macro: {} replaced with: {}", macro, rValue);

            return rValue;
        }
    }

    /**
     * Create an ArrayList by the given String. The String get splitted by given
     * delimeters and one entry in the Array will be made for each splited
     * String
     * 
     * @param data
     *            The String we want to put in the Array
     * @param delimeters
     *            The delimeter we want to use to split the String
     * @return ArrayList which contains the String parts
     */
    private ArrayList<String> split(String data, String delimeters) {

        String currentChar;
        StringBuffer element = new StringBuffer();
        ArrayList<String> splitParts = new ArrayList<String>();

        for (int i = 0; i < data.length(); i++) {
            currentChar = data.substring(i, i + 1);
            if (delimeters.indexOf(currentChar) > -1) {
                splitParts.add(element.toString());
                element.setLength(0);
            } else {
                element.append(currentChar);
            }
        }
        splitParts.add(element.toString());
        return splitParts;
    }

    /**
     * Reverse an ArrayList
     * 
     * @param data
     *            The ArrayList we want to get reversed
     * @return reversed The reversed given ArrayList
     */
    private ArrayList<String> reverse(ArrayList<String> data) {

        ArrayList<String> reversed = new ArrayList<String>();
        for (int i = 0; i < data.size(); i++) {
            reversed.add(0, data.get(i));
        }
        return reversed;
    }

    /**
     * @see #subset(ArrayList, int)
     */
    private String subset(ArrayList<String> data) {
        return subset(data, data.size());
    }

    /**
     * Convert a ArrayList to a String which holds the entries seperated by dots
     * 
     * @param data The ArrayList which should be converted
     * @param length The ArrayLength
     * @return A String which holds all entries seperated by dots
     */
    private String subset(ArrayList<String> data, int length) {

        StringBuffer buildString = new StringBuffer();
        if (data.size() < length) {
            length = data.size();
        }
        int start = data.size() - length;
        for (int i = start; i < data.size(); i++) {
            if (buildString.length() > 0) {
                buildString.append(".");
            }
            buildString.append(data.get(i));
        }
        return buildString.toString();

    }

    /**
     * Encode the given URL to UTF-8
     * 
     * @param data
     *            url to encode
     * @return encoded URL
     */
    private String encodeURL(String data) {

        try {
            // TODO URLEncoder method is not RFC2396 compatible, known
            // difference
            // is Space character gets converted to "+" rather than "%20"
            // Is there anything else which is not correct with URLEncoder?
            // Couldn't find a RFC2396 encoder
            data = URLEncoder.encode(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // This shouldn't happen ignore it!
        }

        // workaround for the above descripted problem
        return data.replaceAll("\\+", "%20");

    }
    
    /**
     * Because Dollar signs may be treated as references to captured subsequences in method Matcher.appendReplacement
     * its necessary to escape Dollar signs because its allowed in the local-part of an emailaddress.
     * 
     * See JSPF-71 for the bugreport
     * 
     * @param raw
     * @return escaped string
     */
    private String escapeForMatcher(String raw) {
        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < raw.length(); i++) {
            char c = raw.charAt(i);
            if (c == '$' || c == '\\') {
                sb.append('\\');
            }
            sb.append(c);
        }
        return sb.toString();
    }

}
