/// <summary>
        /// Generates an icon in the "new content element" wizard to quickly select the plugin
        /// </summary>
        /// <param name="plugin"></param>
        /// <param name="titleLanguageConstant">The name of the language constant in locallang_be that contains the title of the plugin.</param>
        private void GenerateWizard( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin, string titleLanguageConstant )
        {
            string pluginSignature       = NameHelper.GetPluginSignature( Subject, plugin );
              string wizIconScriptFilename = string.Format( "Resources/Private/Php/class.{0}_wizicon.php", pluginSignature );

              // Class registration

              const string registerWizardIconTemplate = "if( TYPO3_MODE == 'BE' ) {{" +
                                                "  $TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses']['{_pluginSignature}_wizicon'] =" +
                                                "    t3lib_extMgm::extPath('{_extensionKey}') . '{_wizIconFilename}';" +
                                                "}}";

              string registerWizardIcon =
            registerWizardIconTemplate.FormatSmart(
              new {_pluginSignature = pluginSignature, _extensionKey = Subject.Key, _wizIconFilename = wizIconScriptFilename} );

              WriteVirtual( "ext_tables.php", registerWizardIcon );

              // Class generation
              string plusWizDescriptionConstant = String.Format( "{0}_plus_wiz_description", plugin.Name.ToLower() );
              WriteVirtual( "Resources/Private/Language/locallang_be.xml", string.Format( "<label index=\"{0}\">Description for {1}</label>", plusWizDescriptionConstant, plugin.Title ) );

              // Flush wizard icon
              string wizIconFilename = string.Format( "ce_wiz_{0}.gif", plugin.Name.ToLower() );
              string wizIconFullFilename = "Resources/Public/Icons/" + wizIconFilename;
              ResourceHelper.FlushIcon( "wiz_icon.gif", this, wizIconFullFilename );

              const string wizIconClassTemplate = "class {_pluginSignature}_wizicon {{" +
                                          "	public function proc($wizardItems) {{" +
                                          "		$locallang = $this->includeLocalLang();" +
                                          "" +
                                          "		$wizardItems['plugins_tx_{_pluginSignature}'] = array(" +
                                          "			'icon'		  	=> t3lib_extMgm::extRelPath('{_extensionKey}') . '{_wizIconFullFilename}'," +
                                          "			'title'		  	=> $GLOBALS['LANG']->getLLL('{_languageConstant}', $locallang)," +
                                          "			'description'	=> $GLOBALS['LANG']->getLLL('{_plusWizDescriptionConstant}', $locallang)," +
                                          "			'params'	  	=> '&defVals[tt_content][CType]=list&defVals[tt_content][list_type]={_pluginSignature}'" +
                                          "		);" +
                                          "" +
                                          "		return $wizardItems;" +
                                          "	}}" +
                                          "	protected function includeLocalLang() {{" +
                                          "		$file = t3lib_extMgm::extPath('{_extensionKey}') . 'Resources/Private/Language/locallang_be.xml';" +
                                          "" +
                                          "		return {_readLLXMLfile};" +
                                          "	}}" +
                                          "}}";

              string wizIconClass =
            wizIconClassTemplate.FormatSmart(
              new {
                _pluginSignature            = pluginSignature,
                _extensionKey               = Subject.Key,
                _languageConstant           = titleLanguageConstant,
                _plusWizDescriptionConstant = plusWizDescriptionConstant,
                _wizIconFullFilename        = wizIconFullFilename,
                _readLLXMLfile              = String.Format( Deprecated.Get( "t3lib_div::readLLXMLfile({0},{1})", GeneratorContext.TargetVersion ), "$file", "$GLOBALS['LANG']->lang" )
              } );

              WritePhpFile( wizIconScriptFilename, wizIconClass, DateTime.UtcNow );
        }
 /// <summary>
 /// Constructs a ConfigurationFileGenerator. 
 /// </summary>
 /// <param name="context">The generator context.</param>
 /// <param name="extension">The extension that should be generated.</param>
 /// <param name="configuration">The model for the configuration that should be generated.</param>
 public ConfigurationFileGenerator( Context context, Extension extension, Typo3ExtensionGenerator.Model.Configuration.Configuration configuration )
     : base(context, extension)
 {
     Configuration = configuration;
 }
        private void GenerateFluidTemplate( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin )
        {
            // The default frontend layout
              const string defaultLayoutTemplate = "<f:render section=\"main\" />";

              const string layoutFilename = "Resources/Private/Layouts/Default.html";
              Log.InfoFormat( "Generating default Fluid layout '{0}'...", layoutFilename );
              WriteFile( layoutFilename, String.Format( defaultLayoutTemplate, Subject.Key ), DateTime.UtcNow );

              // A generic partial that will render all the fields in a model
              //WriteFile( "Resources/Private/Partials/Models/Download.html", string.Empty );

              const string defaultTemplateTemplate = "<f:layout name=\"Default\" />" +
                                             "<f:section name=\"main\">" +
                                             "  <f:flashMessages class=\"flashMessages\" />" +
                                             "  <f:if condition=\"{{debug}}\">" +
                                             "    <f:debug>{{debug}}</f:debug>" +
                                             "  </f:if>" +
                                             "  <h3>You need to create your own Fluid templates and point TYPO3 to them via TypoScript.</h3>" +
                                             "  <p>This is the default template for the action '{_actionTitle}'({_actionName}) of plugin '{_pluginTitle}'({_pluginName}).</p>" +
                                             "</f:section>";

              // Write Fluid templates for each action
              foreach( Action action in plugin.Actions ) {
            // The template that is used for the given action of the given controller
            string templateFilename = string.Format(
              "Resources/Private/Templates/{0}/{1}.html", NameHelper.UpperCamelCase( plugin.Name ),
              NameHelper.UpperCamelCase( action.Name ) );

            Log.InfoFormat( "Generating Fluid template '{0}'...", templateFilename );
            string template =
              defaultTemplateTemplate.FormatSmart(
            new {
                  _actionName = action.Name,
                  _actionTitle = action.Title,
                  _pluginName = plugin.Name,
                  _pluginTitle = plugin.Title
                } );
            WriteFile( templateFilename, template, DateTime.UtcNow );
              }
        }
        /// <summary>
        /// Writes the default TypoScript constants and settings files for the extension.
        /// </summary>
        /// <param name="plugin"> </param>
        private void GenerateTypoScript( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin )
        {
            const string constantsTemplate = "plugin.{pluginName} {{\n" +
                                       "}}";

              const string setupTemplate = "plugin.{pluginName} {{\n" +
                                   "	settings {{\n" +
                                   "	  example {{\n" +
                                   "	    // Place your own TS here\n" +
                                   "	  }}\n" +
                                   "	}}\n" +
                                   "}}";

              // Just to be safe, we also go all lower-case here.
              var dataObject =
            new {
              pluginName   = "tx_" + NameHelper.GetPluginSignature( Subject, plugin ),
              extensionKey = Subject.Key,
              pluginFolder = plugin.Name,
              pluginTitle  = plugin.Title
            };

              Log.Info( "Generating TypoScript constants..." );
              string constants = constantsTemplate.FormatSmart( dataObject );
              WriteFile( string.Format( "Configuration/TypoScript/{0}/constants.txt", plugin.Name ), constants, DateTime.UtcNow );

              Log.Info( "Generating TypoScript setup..." );
              string setup = setupTemplate.FormatSmart( dataObject );
              WriteFile( string.Format( "Configuration/TypoScript/{0}/setup.txt", plugin.Name ), setup, DateTime.UtcNow );

              const string typoScriptRegisterTemplate = "t3lib_extMgm::addStaticFile('{extensionKey}', 'Configuration/TypoScript/{pluginFolder}', '{pluginTitle}');";
              WriteVirtual( "ext_tables.php", typoScriptRegisterTemplate.FormatSmart( dataObject ) );
        }
        /// <summary>
        /// Generates the FlexForm XML for the given plugin.
        /// </summary>
        /// <param name="plugin"></param>
        private void GenerateFlexForm( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin )
        {
            Log.InfoFormat( "Generating FlexForm for '{0}'...", plugin.Name );

              // Collect FlexForms from interfaces
            StringBuilder settings = new StringBuilder();
            StringBuilder actions  = new StringBuilder();

              // TODO: Should possibly render ALL fields in the model
              const string membersTemplate = "\n<settings.{0}><TCEforms>{1}</TCEforms></settings.{0}>";
              foreach( Interface @interface in plugin.Interfaces ) {
            string members = InterfaceGenerator.Generate( this, Subject, @interface, SimpleContainer.Format.XML );

            string setting = string.Format( membersTemplate, @interface.Target, members );
            settings.Append( setting );
              }

              // Generate actions
              const string controllerActionTemplate = "{_controllerName}->{_actionName}";
              const string actionTemplate = "                  <numIndex index=\"{_actIndex}\">" +
                                    "                    <numIndex index=\"0\">{_title}</numIndex>" +
                                    "                    <numIndex index=\"1\">{_controllerName}->{_actionName};{_nonDefault}</numIndex>" +
                                    "                  </numIndex>";

              // We'll generate an entry for each action in the controller.
              // The combination will always list the given action as the first (default) action; all other actions will be allowed in that combination as well.
              int actionIndex = 0;
              foreach( Action action in plugin.Actions ) {
            string nonDefault = plugin.Actions.Where( nonDefaultAction => nonDefaultAction != action ).Aggregate(
              string.Empty, ( current, nonDefaultAction ) => current + ( controllerActionTemplate.FormatSmart(
            new {
                  _controllerName = NameHelper.UpperCamelCase( plugin.Name ),
                  _actionName = nonDefaultAction.Name
                } ) + ";" ) );
            if( !string.IsNullOrEmpty( nonDefault ) ) {
              nonDefault = nonDefault.Substring( 0, nonDefault.Length - 1 );
            }

            var dataObject =
              new {
                _title          = action.Title,
                _controllerName = NameHelper.UpperCamelCase( plugin.Name ),
                _actionName     = action.Name,
                _actIndex       = actionIndex,
                _nonDefault     = nonDefault.ToString()
              };
            string actionString = actionTemplate.FormatSmart( dataObject );
            actions.Append( actionString );

            ++actionIndex;
              }

              string allActions = actions.ToString();
              string allSettings = settings.ToString();
              const string actionsTemplate = "<switchableControllerActions><TCEforms><label>Action</label><config><type>select</type><items>{0}</items></config></TCEforms></switchableControllerActions>";

              const string flexFormTemplate = "<T3DataStructure>" +
                                      "  <meta>" +
                                      "    <langDisable>1</langDisable>" +
                                      "  </meta>" +
                                      "  " +
                                      "  <sheets>" +
                                      "    <sDEF>" +
                                      "      <ROOT>" +
                                      "        <TCEforms>" +
                                      "         <sheetTitle>General</sheetTitle>" +
                                      "        </TCEforms>" +
                                      "        <type>array</type>" +
                                      "        <el>" +
                                      "{actions}" +
                                      "{settings}" +
                                      "        </el>" +
                                      "      </ROOT>" +
                                      "    </sDEF>" +
                                      "  </sheets>" +
                                      "</T3DataStructure>";

              var dataObjectFlexForm = new {settings = allSettings, actions = string.Format( actionsTemplate, allActions )};
              string flexFormsXml = flexFormTemplate.FormatSmart( dataObjectFlexForm );

              // Write final result to file
              WriteVirtual( string.Format( "Configuration/FlexForms/flexform_{0}.xml", plugin.Name.ToLower() ), flexFormsXml );
        }
 /// <summary>
 /// Generates the ExtBase controller for the given plugin.
 /// </summary>
 /// <param name="plugin"></param>
 private void GenerateController( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin )
 {
     ClassProxyGenerator classGenerator = new ClassProxyGenerator( GeneratorContext, Subject );
       classGenerator.GenerateClassProxy( plugin, new ControllerNamingStrategy(), "Classes/Controller/", true );
 }
        /// <summary>
        /// Write all defined language fields to the locallang_db.xml
        /// </summary>
        /// <param name="configuration"></param>
        private void FlushLanguageFields( Typo3ExtensionGenerator.Model.Configuration.Configuration configuration )
        {
            string languageConstant = NameHelper.GetAbsoluteModelName( Subject, configuration.Model );

              WriteVirtual( "Resources/Private/Language/locallang_db.xml", string.Format( "<label index=\"{0}\">{1}</label>", languageConstant, configuration.Title ) );
        }
        public static void Resolve( Fragment parsedFragment, Typo3ExtensionGenerator.Model.Configuration.Interface.Interface @interface, string displayType )
        {
            if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.FileReference == displayType ) {
            SpecializedDisplayType specializedDisplayType = new SpecializedDisplayType {
                                                                                     Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup,
                                                                                     SourceFragment = parsedFragment
                                                                                   };

            specializedDisplayType.Set( "internal_type", "file_reference" );
            specializedDisplayType.Set( "allowed", "*" );
            specializedDisplayType.Set( "disallowed", "php" );
            specializedDisplayType.Set( "size", 5 );
            specializedDisplayType.Set( "maxitems", 99 );

            // If this field requires anything, it should have at least 1 item.
            if( @interface.Settings.Any( s => s.Key == Keywords.Requirement ) ) {
              specializedDisplayType.Set( "minitems", 1 );
            } else {
              specializedDisplayType.Set( "minitems", 0 );
            }

            @interface.DisplayType = specializedDisplayType;

              } else if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup == displayType ) {
            RecordGroupDisplayType recordGroupDisplayType = new RecordGroupDisplayType {
                                                                                     Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup,
                                                                                     SourceFragment = parsedFragment
                                                                                   };

            // Show records next to select box
            recordGroupDisplayType.ShowThumbnails = true;
            // Increase list length
            recordGroupDisplayType.Lines = 10;
            // Increase list width
            recordGroupDisplayType.SelectedListStyle = "width:400px";
            // Don't allow duplicates
            recordGroupDisplayType.AllowDuplicates = false;
            // Set item limit
            recordGroupDisplayType.MaxItems = 99;

            // If this field requires anything, it should have at least 1 item.
            if( @interface.Settings.Any( s => s.Key == Keywords.Requirement ) ) {
              recordGroupDisplayType.MinItems = 1;
            } else {
              recordGroupDisplayType.MinItems = 0;
            }

            // The model type for the suggest wizard is resolved during generation later.
            recordGroupDisplayType.Set( "wizards.RTE.type", "suggest" );

            @interface.DisplayType = recordGroupDisplayType;

              } else if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RichTextArea == displayType ) {
            SpecializedDisplayType specializedDisplayType = new SpecializedDisplayType() {
                                                                                       Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.TextArea,
                                                                                       SourceFragment = parsedFragment
                                                                                     };

            specializedDisplayType.Set( "wizards.RTE.icon", "wizard_rte2.gif" );
            specializedDisplayType.Set( "wizards.RTE.notNewRecords", 1 );
            specializedDisplayType.Set( "wizards.RTE.RTEonly", 1 );
            specializedDisplayType.Set( "wizards.RTE.script", "wizard_rte.php" );
            specializedDisplayType.Set( "wizards.RTE.title", "LLL:EXT:cms/locallang_ttc.xml:bodytext.W.RTE" );
            specializedDisplayType.Set( "wizards.RTE.type", "script" );

            @interface.DisplayType = specializedDisplayType;

            // Add a new property to the interface itself, to enable rich text editing.
            @interface.Set( "defaultExtras", "richtext[]" );

              } else {
            // Could not determine proper display type, use user supplied intput
            @interface.DisplayType = new DisplayType {Name = @interface.DisplayTypeTarget};
              }
        }
        /// <summary>
        /// Generates the interface.
        /// </summary>
        /// <param name="parent">The generator that uses this <see cref="InterfaceGenerator"/>.</param>
        /// <param name="extension">The extension that is being worked on.</param>
        /// <param name="subject">The model for the interface defintion.</param>
        /// <param name="format">The format of the interface.</param>
        /// <returns></returns>
        /// <exception cref="GeneratorException">No display type given in interface.</exception>
        public static string Generate( AbstractGenerator parent, Extension extension, Typo3ExtensionGenerator.Model.Configuration.Interface.Interface subject, SimpleContainer.Format format )
        {
            string propertyTemplate = ( format == SimpleContainer.Format.PhpArray )
                                  ? SimpleContainer.PropertyTemplatePHP
                                  : SimpleContainer.PropertyTemplateXML;

              StringBuilder interfaceDefinition = new StringBuilder();

              // exclude
              interfaceDefinition.Append( string.Format( propertyTemplate, "exclude", subject.Exclude ? "1" : "0" ) );
              // label
              string labelLanguageConstant = string.Format(
            "{0}.{1}", NameHelper.GetAbsoluteModelName( extension, subject.ParentModel ),
            NameHelper.LowerUnderscoredCase( subject.Target ) );

              if( format == SimpleContainer.Format.PhpArray ) {
            interfaceDefinition.Append(
              string.Format(
            propertyTemplate, "label",
            string.Format(
              "'LLL:EXT:{0}/Resources/Private/Language/locallang_db.xml:{1}'", extension.Key,
              labelLanguageConstant ) ) );
              } else {
            interfaceDefinition.Append(
              string.Format(
            propertyTemplate, "label",
            string.Format(
              "LLL:EXT:{0}/Resources/Private/Language/locallang_db.xml:{1}", extension.Key,
              labelLanguageConstant ) ) );
              }

              parent.WriteVirtual( "Resources/Private/Language/locallang_db.xml", string.Format( "<label index=\"{0}\">{1}</label>", labelLanguageConstant, subject.Title ) );

              // config
              string configuration = string.Empty;

              // Add foreign_table
              if( subject.ParentModel.ForeignModels.ContainsKey( subject.Target ) ) {
            DataModel foreignModel = subject.ParentModel.ForeignModels[ subject.Target ];
            string typename = ( String.IsNullOrEmpty( foreignModel.InternalType ) )
                            ? NameHelper.GetAbsoluteModelName( extension, foreignModel )
                            : foreignModel.InternalType;

            subject.DisplayType.ParentModel = foreignModel;

            if( format == SimpleContainer.Format.PhpArray ) {
              configuration += String.Format( propertyTemplate, "foreign_table", "'" + typename + "'" );
              configuration += String.Format( propertyTemplate, "foreign_table_where", "'AND " + typename + ".sys_language_uid=0'" );
              configuration += String.Format( propertyTemplate, "allowed", "'" + typename + "'" );

            } else {
              configuration += String.Format( propertyTemplate, "foreign_table", typename );
              configuration += String.Format( propertyTemplate, "foreign_table_where", "AND " + typename + ".sys_language_uid=0" );
              configuration += String.Format( propertyTemplate, "allowed", typename );
            }
              }

              if( null != subject.DisplayType ) {
            // Add any additional properties to the configuration
            configuration += DisplayTypeGenerator.GeneratePropertyArray( extension, subject.DisplayType, format );

            if( format == SimpleContainer.Format.PhpArray ) {
              configuration += String.Format( propertyTemplate, "type", "'" + subject.DisplayType.Name + "'" );

            } else {
              configuration += String.Format( propertyTemplate, "type", subject.DisplayType.Name );
            }
              } else {
            throw new GeneratorException( string.Format( "No display type given in interface for '{0}'!", subject.Target ), subject.SourceFragment.SourceDocument );
              }

              if( null != subject.DefaultValue ) {
            if( format == SimpleContainer.Format.PhpArray ) {
              configuration += String.Format( propertyTemplate, "default", "'" + subject.DefaultValue + "'" );

            } else {
              configuration += String.Format( propertyTemplate, "default", subject.DefaultValue );
            }
              }

              // Trim trailing comma
              configuration = configuration.TrimEnd( new[] {','} );

              // Add the 'config' array to the interface
              if( format == SimpleContainer.Format.PhpArray ) {
            interfaceDefinition.Append( string.Format( propertyTemplate, "config", "array(" + configuration + ")" ) );
              } else {
            interfaceDefinition.Append( string.Format( propertyTemplate, "config", configuration ) );
              }
              // Add any additional parameters set in the interface
              interfaceDefinition.Append( subject.GeneratePropertyArray( SimpleContainer.Format.PhpArray)  );

              string finalInterface = interfaceDefinition.ToString().TrimEnd( new[] {','} );
              return finalInterface;
        }