/*
 * Copyright 2009-2013 the Fess Project and the Others.
 *
 * Licensed 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 jp.sf.fess.db.allcommon;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.seasar.dbflute.jdbc.Classification;
import org.seasar.dbflute.jdbc.ClassificationCodeType;
import org.seasar.dbflute.jdbc.ClassificationMeta;

/**
 * The definition of classification.
 * @author DBFlute(AutoGenerator)
 */
public interface CDef extends Classification {

    /**
     * Processing Type
     */
    public enum ProcessType implements CDef {
        /** Crawling: Process When Crawling */
        Crawling("C", "Crawling", new String[] {}),
        /** Displaying: Process When Displaying */
        Displaying("D", "Displaying", new String[] {}),
        /** Both: Process When Crawling/Displaying */
        Both("B", "Both", new String[] {});
        private static final Map<String, ProcessType> _codeValueMap = new HashMap<String, ProcessType>();
        static {
            for (final ProcessType value : values()) {
                _codeValueMap.put(value.code().toLowerCase(), value);
                for (final String sister : value.sisters()) {
                    _codeValueMap.put(sister.toLowerCase(), value);
                }
            }
        }

        private final String _code;

        private final String _alias;

        private final String[] _sisters;

        private ProcessType(final String code, final String alias,
                final String[] sisters) {
            _code = code;
            _alias = alias;
            _sisters = sisters;
        }

        @Override
        public String code() {
            return _code;
        }

        @Override
        public String alias() {
            return _alias;
        }

        private String[] sisters() {
            return _sisters;
        }

        @Override
        @SuppressWarnings("unchecked")
        public Map<String, Object> subItemMap() {
            return Collections.EMPTY_MAP;
        }

        @Override
        public ClassificationMeta meta() {
            return CDef.DefMeta.ProcessType;
        }

        /**
         * Get the classification by the code. (CaseInsensitive)
         * @param code The value of code, which is case-insensitive. (NullAllowed: if null, returns null)
         * @return The instance of the corresponding classification to the code. (NullAllowed: if not found, returns null)
         */
        public static ProcessType codeOf(final Object code) {
            if (code == null) {
                return null;
            }
            if (code instanceof ProcessType) {
                return (ProcessType) code;
            }
            return _codeValueMap.get(code.toString().toLowerCase());
        }

        /**
         * Get the classification by the name (also called 'value' in ENUM world).
         * @param name The string of name, which is case-sensitive. (NullAllowed: if null, returns null)
         * @return The instance of the corresponding classification to the name. (NullAllowed: if not found, returns null)
         */
        public static ProcessType nameOf(final String name) { // null allowed
            if (name == null) {
                return null;
            }
            try {
                return valueOf(name);
            } catch (final RuntimeException ignored) {
                return null;
            }
        }

        /**
         * Get the list of all classification elements. (returns new copied list)
         * @return The list of all classification elements. (NotNull)
         */
        public static List<ProcessType> listAll() {
            return new ArrayList<ProcessType>(Arrays.asList(values()));
        }

        @Override
        public String toString() {
            return code();
        }
    }

    /**
     * Access Type
     */
    public enum AccessType implements CDef {
        /** Web: Web */
        Web("W", "Web", new String[] {}),
        /** Mobile: Mobile */
        Mobile("M", "Mobile", new String[] {}),
        /** Xml: Xml */
        Xml("X", "Xml", new String[] {}),
        /** Json: Json */
        Json("J", "Json", new String[] {});
        private static final Map<String, AccessType> _codeValueMap = new HashMap<String, AccessType>();
        static {
            for (final AccessType value : values()) {
                _codeValueMap.put(value.code().toLowerCase(), value);
                for (final String sister : value.sisters()) {
                    _codeValueMap.put(sister.toLowerCase(), value);
                }
            }
        }

        private final String _code;

        private final String _alias;

        private final String[] _sisters;

        private AccessType(final String code, final String alias,
                final String[] sisters) {
            _code = code;
            _alias = alias;
            _sisters = sisters;
        }

        @Override
        public String code() {
            return _code;
        }

        @Override
        public String alias() {
            return _alias;
        }

        private String[] sisters() {
            return _sisters;
        }

        @Override
        @SuppressWarnings("unchecked")
        public Map<String, Object> subItemMap() {
            return Collections.EMPTY_MAP;
        }

        @Override
        public ClassificationMeta meta() {
            return CDef.DefMeta.AccessType;
        }

        /**
         * Get the classification by the code. (CaseInsensitive)
         * @param code The value of code, which is case-insensitive. (NullAllowed: if null, returns null)
         * @return The instance of the corresponding classification to the code. (NullAllowed: if not found, returns null)
         */
        public static AccessType codeOf(final Object code) {
            if (code == null) {
                return null;
            }
            if (code instanceof AccessType) {
                return (AccessType) code;
            }
            return _codeValueMap.get(code.toString().toLowerCase());
        }

        /**
         * Get the classification by the name (also called 'value' in ENUM world).
         * @param name The string of name, which is case-sensitive. (NullAllowed: if null, returns null)
         * @return The instance of the corresponding classification to the name. (NullAllowed: if not found, returns null)
         */
        public static AccessType nameOf(final String name) { // null allowed
            if (name == null) {
                return null;
            }
            try {
                return valueOf(name);
            } catch (final RuntimeException ignored) {
                return null;
            }
        }

        /**
         * Get the list of all classification elements. (returns new copied list)
         * @return The list of all classification elements. (NotNull)
         */
        public static List<AccessType> listAll() {
            return new ArrayList<AccessType>(Arrays.asList(values()));
        }

        @Override
        public String toString() {
            return code();
        }
    }

    public enum DefMeta implements ClassificationMeta {
        /** Processing Type */
        ProcessType,
        /** Access Type */
        AccessType;
        @Override
        public Classification codeOf(final Object code) {
            if ("ProcessType".equals(name())) {
                return CDef.ProcessType.codeOf(code);
            }
            if ("AccessType".equals(name())) {
                return CDef.AccessType.codeOf(code);
            }
            throw new IllegalStateException("Unknown definition: " + this); // basically unreachable
        }

        @Override
        public Classification nameOf(final String name) {
            if ("ProcessType".equals(name())) {
                return CDef.ProcessType.valueOf(name);
            }
            if ("AccessType".equals(name())) {
                return CDef.AccessType.valueOf(name);
            }
            throw new IllegalStateException("Unknown definition: " + this); // basically unreachable
        }

        @Override
        public List<Classification> listAll() {
            if ("ProcessType".equals(name())) {
                return toClassificationList(CDef.ProcessType.listAll());
            }
            if ("AccessType".equals(name())) {
                return toClassificationList(CDef.AccessType.listAll());
            }
            throw new IllegalStateException("Unknown definition: " + this); // basically unreachable
        }

        @SuppressWarnings("unchecked")
        private List<Classification> toClassificationList(final List<?> clsList) {
            return (List<Classification>) clsList;
        }

        @Override
        public ClassificationCodeType codeType() {
            if ("ProcessType".equals(name())) {
                return ClassificationCodeType.String;
            }
            if ("AccessType".equals(name())) {
                return ClassificationCodeType.String;
            }
            return ClassificationCodeType.String; // as default
        }
    }
}
