
package de.ugoe.cs.autoquest.usability.evaluation.result;

import static java.lang.String.format;

import java.util.List;
import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.ExtensionMethod;
import lombok.Getter;

import org.apache.commons.lang.StringUtils;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;

import de.ugoe.cs.autoquest.usability.DefectDescription;
import de.ugoe.cs.autoquest.usability.ParameterFragment;
import de.ugoe.cs.autoquest.usability.util.DefectDescriptionExtensionMethods;

@AllArgsConstructor
@ExtensionMethod({DefectDescriptionExtensionMethods.class})
public class UsabilityDefect {

    @Getter
    private UsabilityDefectSeverityLevel severityLevel;

    private DefectDescription defectDescription;

    private Map<String, String> descriptionParametersValues;

    public String defectDescription() {
        if(defectDescription.containsParameterFragments()) {
            return assembleDefectDescription();
        } else {
            return Joiner.on(" ").skipNulls().join(defectDescription.getTextFragmentOrParameterFragment());
        }
    }

    private String assembleDefectDescription() {
        List<String> descriptionParts = 
                Lists.newArrayListWithCapacity(defectDescription.getTextFragmentOrParameterFragment().size());

        for (Object fragment : defectDescription.getTextFragmentOrParameterFragment()) {
            if (fragment.isParameterFragment()) {
                descriptionParts.add(parameterFragmentAsString((ParameterFragment) fragment));
            } else {
                 descriptionParts.add(CharMatcher.WHITESPACE.collapseFrom((String) fragment, ' ').trim());
            }
        }

        return Joiner.on(' ').join(descriptionParts);
    }

    private String parameterFragmentAsString(ParameterFragment fragment) {
        String value = descriptionParametersValues.getValueOrEmptyString(fragment.getParameterName());
        if (StringUtils.isNotEmpty(value)) {
            return value;
        } else {
            throw new IllegalArgumentException(format("required parameter \"%s\" for usability defect description not provided", fragment.getParameterName()));
        }
    }

}
