/*
 * 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.maven.plugins.assembly.utils;

import java.util.List;

import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
import org.slf4j.Logger;

/**
 *
 */
public final class TypeConversionUtils {

    private static final int U_R = 256;

    private static final int U_W = 128;

    private static final int U_X = 64;

    private static final int G_R = 32;

    private static final int G_W = 16;

    private static final int G_X = 8;

    private static final int W_R = 4;

    private static final int W_W = 2;

    private static final int W_X = 1;

    private TypeConversionUtils() {}

    public static String[] toStringArray(final List<String> list) {
        String[] result = null;

        if ((list != null) && !list.isEmpty()) {
            result = list.toArray(new String[0]);
        }

        return result;
    }

    public static int modeToInt(final String mode, final Logger logger) throws AssemblyFormattingException {
        if (mode == null || mode.trim().length() < 1) {
            return -1;
        }

        try {
            final int value = Integer.parseInt(mode, 8);

            // discard sanity assessment here; we're pushing ahead.
            verifyModeSanity(value, logger);

            return value;
        } catch (final NumberFormatException e) {
            throw new AssemblyFormattingException("Failed to parse mode as an octal number: \'" + mode + "\'.", e);
        }
    }

    // the boolean return type is for people who want to make a decision based on the sanity
    // assessment.
    public static boolean verifyModeSanity(final int mode, final Logger logger) {
        final StringBuilder messages = new StringBuilder();

        messages.append("The mode: ").append(Integer.toString(mode, 8)).append(" contains nonsensical permissions:");

        boolean warn = false;

        // read-access checks.
        if (((mode & U_R) == 0) && ((mode & G_R) == G_R)) {
            messages.append("\n- Group has read access, but user does not.");
            warn = true;
        }

        if (((mode & U_R) == 0) && ((mode & W_R) == W_R)) {
            messages.append("\n- World has read access, but user does not.");
            warn = true;
        }

        if (((mode & G_R) == 0) && ((mode & W_R) == W_R)) {
            messages.append("\n- World has read access, but group does not.");
            warn = true;
        }
        // end read-access checks.

        // write-access checks.
        if (((mode & U_W) == 0) && ((mode & G_W) == G_W)) {
            messages.append("\n- Group has write access, but user does not.");
            warn = true;
        }

        if (((mode & U_W) == 0) && ((mode & W_W) == W_W)) {
            messages.append("\n- World has write access, but user does not.");
            warn = true;
        }

        if (((mode & G_W) == 0) && ((mode & W_W) == W_W)) {
            messages.append("\n- World has write access, but group does not.");
            warn = true;
        }
        // end write-access checks.

        // execute-/list-access checks.
        if (((mode & U_X) == 0) && ((mode & G_X) == G_X)) {
            messages.append("\n- Group has execute/list access, but user does not.");
            warn = true;
        }

        if (((mode & U_X) == 0) && ((mode & W_X) == W_X)) {
            messages.append("\n- World has execute/list access, but user does not.");
            warn = true;
        }

        if (((mode & G_X) == 0) && ((mode & W_X) == W_X)) {
            messages.append("\n- World has execute/list access, but group does not.");
            warn = true;
        }
        // end execute-/list-access checks.

        if (warn && logger != null) {
            logger.warn(messages.toString());
        }

        return !warn;
    }
}
