#include "stdafx.h"

#include "FindType.h"

#include "App.h"


void App::Main(String* args[])
{
    FindType* ft = new FindType();
    try
    {
        SetOptions(args, ft);
        ft->Search();
    }
    catch (SecurityException*)
    {
        Console::WriteLine(S"This sample has failed to run due to a security limitation!\nTry running the sample from a local drive or using CasPol.exe to turn off security.");
    }
    catch(...)
    {
        PrintUsage();
    }
}

void App::PrintUsage()
{
    Console::WriteLine();
    Console::WriteLine(S"FindType [SystemOptions] [MatchOptions] [ShowOptions] [MiscOptions] Name");
    Console::WriteLine(S"");
    Console::WriteLine(S"  where SystemOptions");
    Console::WriteLine(S"   d:[Directory] - Additional directory to search");
    Console::WriteLine(S"  where MatchOptions");
    Console::WriteLine(S"    x - Name = Exact Type Name (including namespace)");
    Console::WriteLine(S"    n - Name = Namespace ");
    Console::WriteLine(S"    w - Match the name anywhere in the namespace");
    Console::WriteLine(S"  where ShowOptions");
    Console::WriteLine(S"    i - Show Interfaces");
    Console::WriteLine(S"    f - Show Fields");
    Console::WriteLine(S"    p - Show Properties");
    Console::WriteLine(S"    e - Show Events");
    Console::WriteLine(S"    m - Show Methods");
    Console::WriteLine(S"    a - Show All Info");
    Console::WriteLine(S"    l - Show Module Information");
    Console::WriteLine(S"  where MiscOptions");
    Console::WriteLine(S"    v = Verbose");
    Console::WriteLine(S"    r = For every type find display base type information");
    Console::WriteLine(S"    ? = Prints Usage information");
    Console::WriteLine();
    Console::WriteLine(S"Examples");
    Console::WriteLine();
    Console::WriteLine(S" FindType String");
    Console::WriteLine(S"   Finds all types that have \'String\' as part of their type name\n");
    Console::WriteLine(S" FindType -r String");
    Console::WriteLine(S"   Finds all types that have \'String\' as part of their name");
    Console::WriteLine(S"   and prints out all base classes\n");
    Console::WriteLine(S" FindType -n System.Reflection");
    Console::WriteLine(S"   Displays all types in the \'System.Reflection\' namespace\n");
    Console::WriteLine(S" FindType -xipm System.String");
    Console::WriteLine(S"   Displays the interfaces, properties and methods on the \'System.String\' type\n");
    Console::WriteLine(S" FindType -d:C:\\ -d:\"C:\\Program Files\\Microsoft.NET\\FrameworkSDK\\Lib\" String");
    Console::WriteLine(S"   Searches DLLs C:\\ and C:\\Program Files\\Microsoft.NET\\FrameworkSDK\\Lib");
    Console::WriteLine(S"   as well as in the current directory \n");
    Console::WriteLine();
}

void App::SetOptions(String* args[], FindType* ft)
{
    if ((int)args.Length == 0)
    {
        PrintUsage();
    }
    else
    {
        ft->VerbosePrint = false;
        Char backslash __gc[] = {'\\'};
        for (int i = 0; i < (int)args.Length; i++)
        {
            String* curArg = args[i];
            if (curArg->Chars[0] != '-' && curArg->Chars[0] != '/')
            {
                ft->ClassAdd(curArg);
            }
            else if (Char::ToUpper(curArg->Chars[1]) != 'D')
            {
                for (int j = 1; j < curArg->Length; j++)
                {
                    switch (Char::ToUpper(curArg->Chars[j]))
                    {
                    case 'X':
                        ft->ExactMatchOnly = true;
                        break;

                    case 'R':
                        ft->RecurseTypes = true;
                        break;

                    case 'V':
                        ft->VerbosePrint = true;
                        break;

                    case 'N':
                        ft->MatchOnlyNamespace = true;
                        break;

                    case 'W':
                        ft->WideSearch = true;
                        break;

                    case 'I':
                        ft->ShowInterfaces = true;
                        break;

                    case 'M':
                        ft->ShowMethods = true;
                        break;

                    case 'F':
                        ft->ShowFields = true;
                        break;

                    case 'P':
                        ft->ShowProperties = true;
                        break;

                    case 'E':
                        ft->ShowEvents = true;
                        break;

                    case 'L':
                        ft->ShowModuleInfo = true;
                        break;

                    case 'A':
                        ft->ShowAll();
                        break;

                    case '?':
                        PrintUsage();
                        break;

                    case 'D':
                        Console::WriteLine(S"Directory not specified");
                        break;

                    default:
                        Console::WriteLine(S"Invald Option[{0}]", __box(curArg->Chars[j]));
                        break;
                    }
                }
            }
            else if (curArg->Length > 2 && curArg->Chars[2] == ':')
            {
                String* dir = curArg->Substring(3)->TrimEnd(backslash)->ToUpper();
                if (dir != S"")
                {
                    ft->DirAdd(dir);
                }
                else
                {
                    Console::WriteLine(S"Directory not specified");
                }
            }
            else
            {
                Console::WriteLine(S"Directory not specified");
            }
        }
    }
}

