/*-
 * Copyright (c) 2017-2024 elementary LLC. (https://elementary.io)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

namespace Scratch.Services.ValaComparison {
    int sort_function (Code.Widgets.SourceList.Item str1, Code.Widgets.SourceList.Item str2) {
        if (!(str1 is ValaSymbolItem && str2 is ValaSymbolItem))
            return str1.name.collate (str2.name);
        var a = (ValaSymbolItem) str1;
        var b = (ValaSymbolItem) str2;
        var sa = a.symbol;
        var sb = b.symbol;
        if (sa is Vala.Class)
            return (compare_class ((Vala.Class) sa, sb));
        else if (sa is Vala.Constant)
            return (compare_constant ((Vala.Constant) sa, sb));
        else if (sa is Vala.Delegate)
            return (compare_delegate ((Vala.Delegate) sa, sb));
        else if (sa is Vala.Constructor)
            return (compare_constructor ((Vala.Constructor) sa, sb));
        else if (sa is Vala.Destructor)
            return (compare_destructor ((Vala.Destructor) sa, sb));
        else if (sa is Vala.CreationMethod)
            return (compare_creationmethod ((Vala.CreationMethod) sa, sb));
        else if (sa is Vala.Enum)
            return (compare_enum ((Vala.Enum) sa, sb));
        else if (sa is Vala.Field)
            return (compare_field ((Vala.Field) sa, sb));
        else if (sa is Vala.Interface)
            return (compare_interface ((Vala.Interface) sa, sb));
        else if (sa is Vala.Method)
            return (compare_method ((Vala.Method) sa, sb));
        else if (sa is Vala.Namespace)
            return (compare_namespace ((Vala.Namespace) sa, sb));
        else if (sa is Vala.Property)
            return (compare_property ((Vala.Property) sa, sb));
        else if (sa is Vala.Signal)
            return (compare_signal ((Vala.Signal) sa, sb));
        else if (sa is Vala.Struct)
            return (compare_struct ((Vala.Struct) sa, sb));
        return str1.name.collate (str2.name);
    }

    int compare_class (Vala.Class s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return 1;
        else if (s2 is Vala.CreationMethod)
            return 1;
        else if (s2 is Vala.Constructor)
            return 1;
        else if (s2 is Vala.Destructor)
            return 1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return 1;
        else if (s2 is Vala.Method)
            return 1;
        else if (s2 is Vala.Namespace)
            return 1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return 1;
        return s.name.collate (s2.name);
    }

    int compare_constant (Vala.Constant s, Vala.Symbol s2) {
        if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return -1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_delegate (Vala.Delegate s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return 1;
        else if (s2 is Vala.Constructor)
            return 1;
        else if (s2 is Vala.Destructor)
            return 1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_constructor (Vala.Constructor s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return 1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_destructor (Vala.Destructor s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return 1;
        else if (s2 is Vala.Constructor)
            return 1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_creationmethod (Vala.CreationMethod s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;

        if (s.name == ".new")
            return -1;

        if (s2.name == ".new")
            return 1;

        return s.name.collate (s2.name);
    }

    int compare_enum (Vala.Enum s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return -1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Field)
            return -1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return 1;
        else if (s2 is Vala.Property)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_field (Vala.Field s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_interface (Vala.Interface s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return 1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_method (Vala.Method s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return 1;
        else if (s2 is Vala.CreationMethod)
            return 1;
        else if (s2 is Vala.Constructor)
            return 1;
        else if (s2 is Vala.Destructor)
            return 1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Signal)
            return 1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_namespace (Vala.Namespace s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return -1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return -1;
        else if (s2 is Vala.Field)
            return -1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Property)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_property (Vala.Property s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return -1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_signal (Vala.Signal s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return 1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return -1;
        else if (s2 is Vala.Field)
            return 1;
        else if (s2 is Vala.Interface)
            return -1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return -1;
        else if (s2 is Vala.Property)
            return 1;
        else if (s2 is Vala.Class)
            return -1;
        else if (s2 is Vala.Struct)
            return -1;
        return s.name.collate (s2.name);
    }

    int compare_struct (Vala.Struct s, Vala.Symbol s2) {
        if (s2 is Vala.Constant)
            return -1;
        else if (s2 is Vala.Delegate)
            return -1;
        else if (s2 is Vala.CreationMethod)
            return -1;
        else if (s2 is Vala.Constructor)
            return -1;
        else if (s2 is Vala.Destructor)
            return -1;
        else if (s2 is Vala.Enum)
            return 1;
        else if (s2 is Vala.Field)
            return -1;
        else if (s2 is Vala.Interface)
            return 1;
        else if (s2 is Vala.Method)
            return -1;
        else if (s2 is Vala.Namespace)
            return 1;
        else if (s2 is Vala.Property)
            return -1;
        else if (s2 is Vala.Signal)
            return -1;
        else if (s2 is Vala.Class)
            return -1;
        return s.name.collate (s2.name);
    }
}
