/**
 * Copyright (C) 2019 Patrik Dufresne Service Logiciel <info@patrikdufresne.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.planimod.ui.databinding;

import static com.planimod.ui.Localized._;

import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.jface.resource.DataFormatException;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.swt.graphics.RGB;

import com.patrikdufresne.util.DateFormatRegistry;

/**
 * Utility class to create converters.
 * 
 * @author Patrik Dufresne
 * 
 */
public class Converters {

    private static final String EMPTY = "";

    /**
     * Create a converter to convert an integer value to an SWT RGB.
     * 
     * @return the converter
     */
    public static IConverter RGBToString() {
        return new Converter(RGB.class, String.class) {
            @Override
            public Object convert(Object fromObject) {
                if (fromObject == null) {
                    return null;
                }
                return StringConverter.asString((RGB) fromObject);
            }
        };
    }

    public static IConverter StringToRGB() {
        return new Converter(String.class, RGB.class) {
            @Override
            public Object convert(Object fromObject) {
                try {
                    return StringConverter.asRGB((String) fromObject);
                } catch (DataFormatException e) {
                    // Don't throw an error within the converter.
                    return null;
                }

            }
        };
    }

    /**
     * Create a converter to convert a date value to a string value. i.e.: Mon 14h30.
     * <p>
     * If the date value is null, an empty string is returned.
     * 
     * @return the converter
     */
    public static IConverter shortDateTimeConverter() {
        return new Converter(Date.class, String.class) {
            @Override
            public Object convert(Object fromObject) {
                if (fromObject == null) {
                    return EMPTY;
                }
                return DateFormatRegistry.format((Date) fromObject, DateFormatRegistry.DATETIME | DateFormatRegistry.SHORT);
            }
        };
    }

    /**
     * Create a converter to convert a date into it's string representation. i.e.: 13 sep 2012.
     * <p>
     * If the date value is null, an empty string is returned.
     * 
     * @return the converter
     */
    public static IConverter shortDateConverter() {
        return new Converter(Date.class, String.class) {

            @Override
            public Object convert(Object fromObject) {
                if (fromObject == null) {
                    return EMPTY;
                }
                return DateFormatRegistry.format((Date) fromObject, DateFormatRegistry.DATE | DateFormatRegistry.SHORT);
            }
        };
    }

    private static IConverter weekTitleConverter;

    /**
     * Create a string label as follow : Semaine du <date>.
     * 
     * @return
     */
    public static IConverter weekTitleConverter() {
        if (weekTitleConverter == null) {
            weekTitleConverter = new Converter(Date.class, String.class) {

                @Override
                public Object convert(Object fromObject) {
                    Date date = (Date) fromObject;
                    return _("Semaine du %s", DateFormatRegistry.format(date, DateFormatRegistry.DATE | DateFormatRegistry.MEDIUM));
                }
            };
        }
        return weekTitleConverter;
    }

    /**
     * Create a converter to convert a boolean value to a string value.
     * 
     * @return the converter
     */
    public static IConverter booleanConverter() {
        return new Converter(Boolean.class, String.class) {

            private static final String X = "X";
            private static final String EMPTY = "";

            @Override
            public Object convert(Object fromObject) {
                if (fromObject == null) {
                    return null;
                }
                return ((Boolean) fromObject).booleanValue() ? X : EMPTY;
            }
        };
    }

    /**
     * Singleton converter.
     */
    private static IConverter removeFrontNumber;

    /**
     * Return a converter to remove the front number of the team or section's name. This function always return the same
     * instance of the converter.
     * 
     * @return the converter.
     */
    public static IConverter removeFrontNumber() {
        if (removeFrontNumber == null) {
            removeFrontNumber = new Converter(String.class, String.class) {

                Pattern pattern;

                @Override
                public Object convert(Object fromObject) {
                    if (fromObject == null) {
                        return null;
                    }
                    if (this.pattern == null) {
                        this.pattern = Pattern.compile("^[0-9]+[ \\.]*");
                    }
                    return this.pattern.matcher(fromObject.toString()).replaceFirst(EMPTY);
                }
            };
        }
        return removeFrontNumber;
    }

}
