// Copyright 2015 Google Inc. All rights reserved.
//
// 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.

// Application that finds all Xcodes installed on a given Mac and will return a
// path for a given version number.
//
// If you have 7.0, 6.4.1 and 6.3 installed the inputs will map to:
//
// 7,7.0,7.0.0 = 7.0
// 6,6.4,6.4.1 = 6.4.1
// 6.3,6.3.0 = 6.3

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

#import <CoreServices/CoreServices.h>
#import <Foundation/Foundation.h>

// Simple data structure for tracking a version of Xcode (i.e. 6.4) with an URL
// to the application.
@interface XcodeVersionEntry : NSObject
@property(readonly) NSString *version;
@property(readonly) NSString *productVersion;
@property(readonly) NSURL *url;
@end

@implementation XcodeVersionEntry

- (id)initWithVersion:(NSString *)version
       productVersion:(NSString *)productVersion
                  url:(NSURL *)url {
  if ((self = [super init])) {
    _version = version;
    _productVersion = productVersion;
    _url = url;
  }
  return self;
}

- (id)description {
  return [NSString stringWithFormat:@"<%@ %p>: %@ %@",
                   [self class], self, _version, _url];
}

@end

// Given an entry, insert it into a dictionary that is keyed by versions.
//
// For an entry that is 6.4.1:/Applications/Xcode.app, add it for 6.4.1 and
// optionally add it for 6.4 and 6 if it is "better" than any entry that may
// already be there, where "better" is defined as:
//
// 1. Under /Applications/. (This avoids mounted xcode versions taking
//    precedence over installed versions.)
//
// 2. Not older (at least as high version number).
static void AddEntryToDictionary(
  XcodeVersionEntry *entry,
  NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict) {
  BOOL inApplications = [entry.url.path hasPrefix:@"/Applications/"];
  NSString *entryVersion = entry.version;
  NSString *entryProductVersion = entry.productVersion;
  NSString *subversion = entryVersion;
  if (dict[entryVersion] && !inApplications) {
    return;
  }
  dict[entryVersion] = entry;
  if (entryProductVersion) {
    dict[entryProductVersion] = entry;
  }
  while (YES) {
    NSRange range = [subversion rangeOfString:@"." options:NSBackwardsSearch];
    if (range.length == 0 || range.location == 0) {
      break;
    }
    subversion = [subversion substringToIndex:range.location];
    XcodeVersionEntry *subversionEntry = dict[subversion];
    if (subversionEntry) {
      BOOL atLeastAsLarge =
          ([subversionEntry.version compare:entry.version
                                    options:NSNumericSearch] != NSOrderedDescending);
      if (inApplications && atLeastAsLarge) {
        dict[subversion] = entry;
      }
    } else {
      dict[subversion] = entry;
    }
  }
}

// Given a "version", expand it to at least 3 components by adding .0 as
// necessary.
static NSString *ExpandVersion(NSString *version) {
  NSArray *components = [version componentsSeparatedByString:@"."];
  NSString *appendage = nil;
  if (components.count == 2) {
    appendage = @".0";
  } else if (components.count == 1) {
    appendage = @".0.0";
  }
  if (appendage) {
    version = [version stringByAppendingString:appendage];
  }
  return version;
}

// Searches for all available Xcodes in the system and returns a dictionary that
// maps version identifiers of any form (X, X.Y, and X.Y.Z) to the directory
// where the Xcode bundle lives.
//
// If there is a problem locating the Xcodes, prints one or more error messages
// and returns nil.
static NSMutableDictionary<NSString *, XcodeVersionEntry *> *FindXcodes()
  __attribute((ns_returns_retained)) {
  CFStringRef cfBundleID = CFSTR("com.apple.dt.Xcode");
  NSString *bundleID = (__bridge NSString *)cfBundleID;

  NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict =
      [[NSMutableDictionary alloc] init];
  CFErrorRef cfError;
  NSArray *array = CFBridgingRelease(LSCopyApplicationURLsForBundleIdentifier(
      cfBundleID, &cfError));
  if (array == nil) {
    NSError *nsError = (__bridge NSError *)cfError;
    fprintf(stderr, "error: %s\n", nsError.description.UTF8String);
    return nil;
  }

  // Scan all bundles but delay returning in case of errors until we are
  // done. This is to let us log details about all the bundles that were
  // processed so that a faulty bundle doesn't hide useful information about
  // other bundles that were found.
  BOOL errors = NO;
  for (NSURL *url in array) {
    NSArray *contents = [
      [NSFileManager defaultManager] contentsOfDirectoryAtURL:url
                                   includingPropertiesForKeys:nil
                                                      options:0
                                                        error:nil];
    NSLog(@"Found bundle %@ in %@; contents on disk: %@",
          bundleID, url, contents);

    NSBundle *bundle = [NSBundle bundleWithURL:url];
    if (bundle == nil) {
      NSLog(@"ERROR: Unable to open bundle at URL: %@\n", url);
      errors = YES;
      continue;
    }

    // LSCopyApplicationURLsForBundleIdentifier seems to sometimes return
    // invalid bundles (e.g. an arbitrary folder), which we should ignore (but
    // don't treat as an error).
    //
    // To work around this issue, we double check to make sure the NSBundle's
    // bundleIdentifier is that of Xcode's, as invalid bundles won't match.
    if (![bundle.bundleIdentifier isEqualToString:bundleID]) {
      NSLog(@"WARNING: Ignoring bundle %@ due to bundleID mismatch "
            @"(got \"%@\" but expected \"%@\"); info: %@",
            url, bundle.bundleIdentifier, bundleID, bundle.infoDictionary);
      continue;
    }

    NSString *versionKey = @"CFBundleShortVersionString";
    NSString *version = [bundle.infoDictionary objectForKey:versionKey];
    if (version == nil) {
      NSLog(@"ERROR: Cannot find %@ in info for bundle %@; info: %@\n",
            versionKey, url, bundle.infoDictionary);
      errors = YES;
      continue;
    }
    NSString *expandedVersion = ExpandVersion(version);
    NSLog(@"Version strings for %@: short=%@, expanded=%@",
          url, version, expandedVersion);

    NSURL *versionPlistUrl = [url URLByAppendingPathComponent:@"Contents/version.plist"];
    NSDictionary *versionPlistContents =
        [[NSDictionary alloc] initWithContentsOfURL:versionPlistUrl];
    NSString *productVersion = [versionPlistContents objectForKey:@"ProductBuildVersion"];
    if (productVersion) {
      expandedVersion = [expandedVersion stringByAppendingFormat:@".%@", productVersion];
    }

    NSURL *developerDir =
        [url URLByAppendingPathComponent:@"Contents/Developer"];
    XcodeVersionEntry *entry = [[XcodeVersionEntry alloc] initWithVersion:expandedVersion
                                                           productVersion:productVersion
                                                                      url:developerDir];
    AddEntryToDictionary(entry, dict);
  }
  return errors ? nil : dict;
}

// Prints out the located Xcodes as a set of lines where each line contains the
// list of versions for a given Xcode and its location on disk.
static void DumpAsVersionsOnly(
  FILE *output,
  NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict) {
  NSMutableDictionary<NSString *, NSMutableSet <NSString *> *> *aliasDict =
      [[NSMutableDictionary alloc] init];
  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *aliasVersion,
                                            XcodeVersionEntry *entry,
                                            BOOL *stop) {
    NSString *versionString = entry.version;
    if (aliasDict[versionString] == nil) {
      aliasDict[versionString] = [[NSMutableSet alloc] init];
    }
    [aliasDict[versionString] addObject:aliasVersion];
  }];
  for (NSString *version in aliasDict) {
    XcodeVersionEntry *entry = dict[version];
    fprintf(output, "%s:%s:%s\n",
            version.UTF8String,
            [[aliasDict[version] allObjects]
                   componentsJoinedByString: @","].UTF8String,
            entry.url.fileSystemRepresentation);
  }
}

// Prints out the located Xcodes in JSON format.
static void DumpAsJson(
  FILE *output,
  NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict) {
  fprintf(output, "{\n");
  int i = 0;
  for (NSString *version in dict) {
    XcodeVersionEntry *entry = dict[version];
    fprintf(output, "\t\"%s\": \"%s\"%s\n",
            version.UTF8String, entry.url.fileSystemRepresentation,
            ++i == [dict count] ? "" : ",");
  }
  fprintf(output, "}\n");
}

// Dumps usage information.
static void usage(FILE *output) {
  fprintf(
      output,
      "xcode-locator [-v|<version_number>]"
      "\n\n"
      "Given a version number or partial version number in x.y.z format, "
      "will attempt to return the path to the appropriate developer "
      "directory."
      "\n\n"
      "Omitting a version number will list all available versions in JSON "
      "format, alongside their paths."
      "\n\n"
      "Passing -v will list all available fully-specified version numbers "
      "along with their possible aliases and their developer directory, "
      "each on a new line. For example:"
      "\n\n"
      "7.3.1:7,7.3,7.3.1:/Applications/Xcode.app/Contents/Developer"
      "\n");
}

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    NSString *versionArg = nil;
    BOOL versionsOnly = NO;
    if (argc == 1) {
      versionArg = @"";
    } else if (argc == 2) {
      NSString *firstArg = [NSString stringWithUTF8String:argv[1]];
      if ([@"-v" isEqualToString:firstArg]) {
        versionsOnly = YES;
        versionArg = @"";
      } else {
        versionArg = firstArg;
      }
    }
    if (versionArg == nil) {
      usage(stderr);
      return 1;
    }

    NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict = FindXcodes();
    if (dict == nil) {
      return 1;
    }

    XcodeVersionEntry *entry = [dict objectForKey:versionArg];
    if (entry) {
      printf("%s\n", entry.url.fileSystemRepresentation);
      return 0;
    }

    if (versionsOnly) {
      DumpAsVersionsOnly(stdout, dict);
    } else {
      DumpAsJson(stdout, dict);
    }
    return ([@"" isEqualToString:versionArg] ? 0 : 1);
  }
}
