using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.Proxy;
using System.Configuration;
using System.IO;
using System.Collections.Specialized;
using System.Reflection;
using System.Collections;
using System.Diagnostics;

namespace TFSWrappers
{
    public class BuildStoreWrapper
    {
        public BuildStoreWrapper(ConfigurationType configurationType)
        {
            NameValueCollection appSettings = TFSFunctions.GetTFSAppSettingsSection(configurationType); 
            InitWrapper(appSettings);
        }

        private void InitWrapper(NameValueCollection appSettings)
        {
            string serverName = appSettings[TFSConstants.ServerAppSettingsValueName];
            project = appSettings[TFSConstants.ProjectAppSettingsValueName];
            tfs = TFSFunctions.GetServer(serverName);
            bs = (BuildStore)tfs.GetService(typeof(BuildStore));
        }

        public BuildStoreWrapper(string serverName)
        {
            tfs = TFSFunctions.GetServer(serverName);
            bs = (BuildStore)tfs.GetService(typeof(BuildStore));
        }

        public BuildStoreWrapper(string serverName, string teamProject)
        {
            tfs = TFSFunctions.GetServer(serverName);
            bs = (BuildStore)tfs.GetService(typeof(BuildStore));
            project = teamProject;
        }

        public BuildStoreWrapper(TeamFoundationServer tfs)
        {
            this.tfs = tfs;
            bs = (BuildStore)tfs.GetService(typeof(BuildStore));
        }

        private string project;

        public string Project
        {
            get { return project; }
        }

        private TeamFoundationServer tfs;

        public TeamFoundationServer TFS
        {
            get { return tfs; }
        }

        private BuildStore bs;

        public BuildStore BS
        {
            get { return bs; }
        }

        public string[] GetBuilds(string teamProject, string buildType, string buildQuality, string buildStatus)
        {
            List<string> buildTypes = new List<string>();
            if (buildType == String.Empty)
            {
                string[] buildTypesArray = GetBuildTypes(teamProject);
                buildTypes.AddRange(buildTypesArray);
            }
            else
            {
                buildTypes.Add(buildType);
            }
            List<string> builds = new List<string>();
            foreach (string buildTypeItem in buildTypes)
            {
                BuildData[] buildsData = BS.GetListOfBuilds(teamProject, buildTypeItem);
                foreach (BuildData buildData in buildsData)
                {
                    if (((String.Compare(buildData.BuildQuality, buildQuality, true) == 0) ||
                        (buildQuality == String.Empty)) &&
                        ((String.Compare(buildData.BuildStatus, buildStatus, true) == 0) ||
                        (buildStatus == String.Empty)))
                    {
                        builds.Add(buildData.BuildNumber);
                    }
                }
            }
            return builds.ToArray();
        }


        public string[] GetBuilds(string teamProject, string buildType, string buildQuality)
        {
            return GetBuilds(teamProject, buildType, buildQuality, String.Empty);
        }

        public string[] GetBuilds(string teamProject, string buildType)
        {
            return GetBuilds(teamProject, buildType, String.Empty);
        }

        public string[] GetBuilds(string teamProject)
        {
            return GetBuilds(teamProject, String.Empty);
        }

        public string[] GetBuildQualities()
        {
            return BS.GetBuildQualities();
        }

        public static string[] GetBuildStatuses()
        {
            Type t = typeof(Microsoft.TeamFoundation.Build.Common.BuildConstants.BuildStatus);
            ArrayList constants = new ArrayList();
            PropertyInfo[] propertyInfos = t.GetProperties(BindingFlags.Public | BindingFlags.Static |
                BindingFlags.FlattenHierarchy);
            List<string> buildStatuses = new List<string>();
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                if (propertyInfo.PropertyType == typeof(string))
                {
                    buildStatuses.Add(propertyInfo.GetValue(null, new object[] { }).ToString());
                }
            }
            return buildStatuses.ToArray();
        }

        public string[] GetBuildTypes(string teamProject)
        {
            SourceControlWrapper sourceControlWrapper = new SourceControlWrapper(tfs);
            string[] folders = sourceControlWrapper.GetFolders("$/" + teamProject + "/TeamBuildTypes", false);
            List<string> buildTypes = new List<string>();
            foreach (string folder in folders)
            {
                string buildType = Path.GetFileName(folder);
                if (buildType != "TeamBuildTypes")
                {
                    buildTypes.Add(buildType);
                }
            }
            return buildTypes.ToArray();
        }
        
        private BuildData GetBuildData(string teamProject, string buildNumber)
        {
            BuildData buildData = BS.GetBuildDetails(BS.GetBuildUri(teamProject, buildNumber));
            return buildData;
        }

        public string[] GetBuildFlavors(string teamProject, string buildNumber)
        {
            BuildData buildData = GetBuildData(teamProject, buildNumber);
            List<string> flavors = new List<string>();
            PlatformFlavorData[] platformFlavorsData = BS.GetPlatformFlavorsForBuild(BS.GetBuildUri(teamProject, buildNumber));
            foreach (PlatformFlavorData platformFlavorData in platformFlavorsData)
            {
                flavors.Add(platformFlavorData.FlavorName);
            }
            return flavors.ToArray();
        }

        public string GetBuildDropLocation(string teamProject, string buildNumber)
        {
            BuildData buildData = GetBuildData(teamProject, buildNumber);
            return buildData.DropLocation;
        }

        public string GetBuildQuality(string teamProject, string buildNumber)
        {
            BuildData buildData = GetBuildData(teamProject, buildNumber);
            return buildData.BuildQuality;
        }

        public ChangeSetData[] GetBuildChangeSets(string buildNumber)
        {
            return GetBuildChangeSets(project, buildNumber);
        }

        public ChangeSetData[] GetBuildChangeSets(string teamProject, string buildNumber)
        {
            string buildUri = BS.GetBuildUri(project, buildNumber);
            return BS.GetChangeSetsForBuild(buildUri);
        }

        public void UpdateBuildQuality(string teamProject, string buildNumber, string buildQuality)
        {
            BS.UpdateBuildQuality(BS.GetBuildUri(teamProject, buildNumber), buildQuality);
        }
    }
}
