package com.atlassian.stash.internal.web.soy.functions;

import com.atlassian.soy.renderer.JsExpression;
import com.atlassian.soy.renderer.SoyClientFunction;
import com.atlassian.soy.renderer.SoyServerFunction;

import java.util.Collections;
import java.util.Locale;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;

public class CamelCaseToHyphenatedFunction implements SoyServerFunction<String>, SoyClientFunction {
    public static final Set<Integer> VALID_ARG_SIZES = Collections.singleton(1);

    @Override
    public String getName() {
        return "camel_case_to_hyphenated";
    }

    @Override
    public JsExpression generate(JsExpression... args) {
        return new JsExpression("require('bitbucket/internal/util/text').camelCaseToHyphenated(" + args[0].getText() + ")");
    }

    @Override
    public String apply(Object... args) {
        Object text = args[0];
        checkArgument(text instanceof String, "invalid argument: %s", text);

        return hyphenate((String) text);
    }

    private String hyphenate(String text) {
        //Prefix any uppercase character that is preceded by a character that is not a hyphen, underscore or whitespace with a hyphen and lowercase the whole string
        //Replace any spaces with hyphens but really, this is intended to be used with well-formed camelcase,
        //if you pass in rubbish it will do it's best to LITFA but it will probably not be able to be reliably reversed.
        //This should be kept in sync with the JS implementation in `util/text`
        return text.replaceAll("(?<=[^-_\\s])([A-Z])", "-$1").replaceAll("\\s", "-").toLowerCase(Locale.US);
    }

    @Override
    public Set<Integer> validArgSizes() {
        return VALID_ARG_SIZES;
    }
}
