<?php

class LibraryController extends Zend_Controller_Action
{
    public function init()
    {
        $ajaxContext = $this->_helper->getHelper('AjaxContext');
        $ajaxContext->addActionContext('contents-feed', 'json')
            ->addActionContext('delete', 'json')
            ->addActionContext('duplicate', 'json')
            ->addActionContext('duplicate-block', 'json')
            ->addActionContext('delete-group', 'json')
            ->addActionContext('context-menu', 'json')
            ->addActionContext('get-file-metadata', 'html')
            ->addActionContext('set-num-entries', 'json')
            ->addActionContext('edit-file-md', 'json')
            ->addActionContext('publish-dialog', 'html')
            ->initContext();
    }

    public function indexAction()
    {
        $this->_redirect('showbuilder');
    }

    protected function playlistNotFound($p_type)
    {
        $this->view->error = sprintf(_('%s not found'), $p_type);

        Logging::info("{$p_type} not found");
        Application_Model_Library::changePlaylist(null, $p_type);
        $this->createFullResponse(null);
    }

    protected function playlistUnknownError($e)
    {
        $this->view->error = _('Something went wrong.');
        Logging::info($e->getMessage());
    }

    protected function createFullResponse($obj = null, $isJson = false)
    {
        $isBlock = false;
        $viewPath = 'playlist/playlist.phtml';
        if ($obj instanceof Application_Model_Block) {
            $isBlock = true;
            $viewPath = 'playlist/smart-block.phtml';
        }

        if (isset($obj)) {
            $formatter = new LengthFormatter($obj->getLength());
            $this->view->length = $formatter->format();

            if ($isBlock) {
                $form = new Application_Form_SmartBlockCriteria();
                $form->removeDecorator('DtDdWrapper');
                $form->startForm($obj->getId());

                $this->view->form = $form;
                $this->view->obj = $obj;
                $this->view->id = $obj->getId();
                if ($isJson) {
                    return $this->view->render($viewPath);
                }
                $this->view->html = $this->view->render($viewPath);
            } else {
                $this->view->obj = $obj;
                $this->view->id = $obj->getId();
                $this->view->html = $this->view->render($viewPath);
                unset($this->view->obj);
            }
        } else {
            $this->view->html = $this->view->render($viewPath);
        }
    }

    public function contextMenuAction()
    {
        $baseUrl = Config::getBasePath();
        $id = $this->_getParam('id');
        $type = $this->_getParam('type');
        // playlist||timeline
        $screen = $this->_getParam('screen');

        $menu = [];

        $userInfo = Zend_Auth::getInstance()->getStorage()->read();
        $user = new Application_Model_User($userInfo->id);

        // Open a jPlayer window and play the audio clip.
        $menu['play'] = ['name' => _('Preview'), 'icon' => 'play', 'disabled' => false];

        $isAdminOrPM = $user->isUserType([UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER]);

        $obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);

        if ($type === 'audioclip') {
            $file = Application_Model_StoredFile::RecallById($id);

            $menu['play']['mime'] = $file->getPropelOrm()->getDbMime();

            if (isset($obj_sess->id) && $screen == 'playlist') {
                // if the user is not admin or pm, check the creator and see if this person owns the playlist or Block
                if ($obj_sess->type == 'playlist') {
                    $obj = new Application_Model_Playlist($obj_sess->id);
                } elseif ($obj_sess->type == 'block') {
                    $obj = new Application_Model_Block($obj_sess->id);
                }
                if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                    if ($obj_sess->type === 'playlist') {
                        $menu['pl_add'] = ['name' => _('Add to Playlist'), 'icon' => 'add-playlist', 'icon' => 'copy'];
                    } elseif ($obj_sess->type === 'block' && $obj->isStatic()) {
                        $menu['pl_add'] = ['name' => _('Add to Smart Block'), 'icon' => 'add-playlist', 'icon' => 'copy'];
                    }
                }
            }
            if ($isAdminOrPM || $file->getFileOwnerId() == $user->getId()) {
                $menu['del'] = ['name' => _('Delete'), 'icon' => 'delete', 'url' => $baseUrl . 'library/delete'];
                $menu['edit'] = ['name' => _('Edit...'), 'icon' => 'edit', 'url' => $baseUrl . "library/edit-file-md/id/{$id}"];
                // Disable My podcasts
                // See https://github.com/libretime/libretime/issues/1320
                // $menu["publish"] = array("name"=> _("Publish..."), "url" => $baseUrl."library/publish/id/{$id}");
            }

            $url = $baseUrl . "api/get-media/file/{$id}/download/true";
            $menu['download'] = ['name' => _('Download'), 'icon' => 'download', 'url' => $url];
        } elseif ($type === 'playlist' || $type === 'block') {
            if ($type === 'playlist') {
                $obj = new Application_Model_Playlist($id);
                $menu['duplicate'] = ['name' => _('Duplicate Playlist'), 'icon' => 'edit', 'url' => $baseUrl . 'library/duplicate'];
            } elseif ($type === 'block') {
                $obj = new Application_Model_Block($id);
                $menu['duplicate'] = ['name' => _('Duplicate Smartblock'), 'icon' => 'edit', 'url' => $baseUrl . 'library/duplicate-block'];
                if (!$obj->isStatic()) {
                    unset($menu['play']);
                }
                if (($isAdminOrPM || $obj->getCreatorId() == $user->getId()) && $screen == 'playlist') {
                    if ($obj_sess->type === 'playlist') {
                        $menu['pl_add'] = ['name' => _('Add to Playlist'), 'icon' => 'add-playlist', 'icon' => 'copy'];
                    }
                }
            }

            if ($obj_sess->id !== $id && $screen == 'playlist') {
                if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                    $menu['edit'] = ['name' => _('Edit...'), 'icon' => 'edit'];
                }
            }

            if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                $menu['del'] = ['name' => _('Delete'), 'icon' => 'delete', 'url' => $baseUrl . 'library/delete'];
            }
        } elseif ($type == 'stream') {
            $webstream = CcWebstreamQuery::create()->findPK($id);
            $obj = new Application_Model_Webstream($webstream);

            $menu['play']['mime'] = $webstream->getDbMime();

            if (isset($obj_sess->id) && $screen == 'playlist') {
                if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                    if ($obj_sess->type === 'playlist') {
                        $menu['pl_add'] = ['name' => _('Add to Playlist'), 'icon' => 'add-playlist', 'icon' => 'copy'];
                    }
                }
            }
            if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                if ($screen == 'playlist') {
                    $menu['edit'] = ['name' => _('Edit...'), 'icon' => 'edit', 'url' => $baseUrl . "library/edit-file-md/id/{$id}"];
                }
                $menu['del'] = ['name' => _('Delete'), 'icon' => 'delete', 'url' => $baseUrl . 'library/delete'];
            }
        }

        if (empty($menu)) {
            $menu['noaction'] = ['name' => _('No action available')];
        }

        $this->view->items = $menu;
    }

    public function deleteAction()
    {
        // array containing id and type of media to delete.
        $mediaItems = $this->_getParam('media', null);

        $user = Application_Model_User::getCurrentUser();
        // $isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));

        $files = [];
        $playlists = [];
        $blocks = [];
        $streams = [];

        $message = null;
        $noPermissionMsg = _("You don't have permission to delete selected items.");

        foreach ($mediaItems as $media) {
            if ($media['type'] === 'audioclip') {
                $files[] = intval($media['id']);
            } elseif ($media['type'] === 'playlist') {
                $playlists[] = intval($media['id']);
            } elseif ($media['type'] === 'block') {
                $blocks[] = intval($media['id']);
            } elseif ($media['type'] === 'stream') {
                $streams[] = intval($media['id']);
            }
        }

        try {
            Application_Model_Playlist::deletePlaylists($playlists, $user->getId());
        } catch (PlaylistNoPermissionException $e) {
            $message = $noPermissionMsg;
        }

        try {
            Application_Model_Block::deleteBlocks($blocks, $user->getId());
        } catch (BlockNoPermissionException $e) {
            $message = $noPermissionMsg;
        } catch (Exception $e) {
            // TODO: warn user that not all blocks could be deleted.
        }

        try {
            Application_Model_Webstream::deleteStreams($streams, $user->getId());
        } catch (WebstreamNoPermissionException $e) {
            $message = $noPermissionMsg;
        } catch (Exception $e) {
            // TODO: warn user that not all streams could be deleted.
            Logging::info($e);
        }

        foreach ($files as $id) {
            $file = Application_Model_StoredFile::RecallById($id);
            if (isset($file)) {
                try {
                    $res = $file->delete();
                } catch (FileNoPermissionException $e) {
                    $message = $noPermissionMsg;
                } catch (DeleteScheduledFileException $e) {
                    $message = _('Could not delete file because it is scheduled in the future.');
                } catch (Exception $e) {
                    // could throw a scheduled in future exception.
                    $message = _('Could not delete file(s).');
                    Logging::info($message . ': ' . $e->getMessage());
                }
            }
        }

        if (isset($message)) {
            $this->view->message = $message;
        }
    }

    // duplicate playlist
    public function duplicateAction()
    {
        $params = $this->getRequest()->getParams();
        $id = $params['id'];
        Logging::info($params);

        $originalPl = new Application_Model_Playlist($id);
        $newPl = new Application_Model_Playlist();

        $contents = $originalPl->getContents();
        foreach ($contents as &$c) {
            if ($c['type'] == '0') {
                $c[1] = 'audioclip';
            } elseif ($c['type'] == '2') {
                $c[1] = 'block';
            } elseif ($c['type'] == '1') {
                $c[1] = 'stream';
            }
            $c[0] = $c['item_id'];
        }

        $newPl->addAudioClips($contents, null, 'before');

        $newPl->setCreator(Application_Model_User::getCurrentUser()->getId());
        $newPl->setDescription($originalPl->getDescription());

        [$plFadeIn] = $originalPl->getFadeInfo(0);
        [, $plFadeOut] = $originalPl->getFadeInfo($originalPl->getSize() - 1);

        $newPl->setfades($plFadeIn, $plFadeOut);
        $newPl->setName(sprintf(_('Copy of %s'), $originalPl->getName()));
    }

    // duplicate smartblock
    public function duplicateBlockAction()
    {
        Logging::info('duplicate smartblock functionality not yet implemented');
        $params = $this->getRequest()->getParams();
        $id = $params['id'];
        Logging::info($params);

        $originalBl = new Application_Model_Block($id);
        $newBl = new Application_Model_Block();
        $newBl->setCreator(Application_Model_User::getCurrentUser()->getId());
        $newBl->setDescription($originalBl->getDescription());
        if ($originalBl->isStatic()) {
            $newBl->saveType('static');
        } else {
            $newBl->saveType('dynamic');
        }
        // the issue here is that the format that getCriteria provides is different from the format the saveCriteria
        // expects due to the useage of startForm. So we either need to write new code that simply copies the database
        // or figure out a way to instantiate a form inside of here and save it without modifying it.
        // $newBlForm = new Application_Form_SmartBlockCriteria;
        // $newBlForm->startForm($id);
        $criteria = CcBlockcriteriaQuery::create()->orderByDbCriteria()->findByDbBlockId($id);
        foreach ($criteria as &$c) {
            $row = new CcBlockcriteria();
            $row->setDbCriteria($c->getDbCriteria());
            $row->setDbModifier($c->getDbModifier());
            $row->setDbValue($c->getDbValue());
            $row->setDbExtra($c->getDbExtra());
            $row->setDbBlockId($newBl->getId());
            $row->save();
        }
        $newBl->setName(sprintf(_('Copy of %s'), $originalBl->getName()));
    }

    public function contentsFeedAction()
    {
        $params = $this->getRequest()->getParams();

        // terrible name for the method below. it does not only search files.
        $r = Application_Model_StoredFile::searchLibraryFiles($params);

        $this->view->sEcho = $r['sEcho'];
        $this->view->iTotalDisplayRecords = $r['iTotalDisplayRecords'];
        $this->view->iTotalRecords = $r['iTotalRecords'];
        $this->view->files = SecurityHelper::htmlescape_recursive($r['aaData']);
    }

    public function editFileMdAction()
    {
        $user = Application_Model_User::getCurrentUser();
        $isAdminOrPM = $user->isUserType([UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER]);
        $isAdmin = $user->isUserType([UTYPE_SUPERADMIN, UTYPE_ADMIN]);

        $request = $this->getRequest();

        $file_id = $this->_getParam('id', null);
        $file = Application_Model_StoredFile::RecallById($file_id);

        $form = new Application_Form_EditAudioMD();
        $form->startForm($file_id);
        $form->populate($file->getDbColMetadata());

        $this->view->permissionDenied = false;
        if (!$isAdminOrPM && $file->getFileOwnerId() != $user->getId()) {
            $form->makeReadOnly();
            $form->removeActionButtons();
            $this->view->permissionDenied = true;
        }
        // only admins should be able to edit the owner of a file
        if (!$isAdmin) {
            $form->removeOwnerEdit();
        }

        if ($request->isPost()) {
            $js = $this->_getParam('data');
            $serialized = [];
            // need to convert from serialized jQuery array.
            foreach ($js as $j) {
                // on edit, if no artwork is set and audiofile has image, automatically add it
                if ($j['name'] == 'artwork') {
                    if ($j['value'] == null || $j['value'] == '') {
                        $serialized['artwork'] = FileDataHelper::resetArtwork($file_id);
                    }
                } elseif ($j['name'] == 'set_artwork') {
                    if ($j['value'] != null || $j['value'] != '') {
                        $serialized['artwork'] = FileDataHelper::setArtwork($file_id, $j['value']);
                    }
                } elseif ($j['name'] == 'remove_artwork') {
                    if ($j['value'] == 1) {
                        $remove_artwork = true;
                        $serialized['artwork'] = FileDataHelper::removeArtwork($file_id);
                    }
                } else {
                    $serialized[$j['name']] = $j['value'];
                }
            }

            // Sanitize any wildly incorrect metadata before it goes to be validated.
            FileDataHelper::sanitizeData($serialized);

            if ($form->isValid($serialized)) {
                $file->setDbColMetadata($serialized);
                $this->view->status = true;
            } else {
                $this->view->status = false;
            }
        }

        $this->view->form = $form;
        $this->view->id = $file_id;
        $this->view->title = $file->getPropelOrm()->getDbTrackTitle();
        $this->view->artist_name = $file->getPropelOrm()->getDbArtistName();
        $this->view->filePath = $file->getPropelOrm()->getDbFilepath();
        $this->view->artwork = $file->getPropelOrm()->getDbArtwork();
        $this->view->html = $this->view->render('library/edit-file-md.phtml');
    }

    public function getFileMetadataAction()
    {
        $id = $this->_getParam('id');
        $type = $this->_getParam('type');

        try {
            if ($type == 'audioclip') {
                $file = Application_Model_StoredFile::RecallById($id);
                $this->view->type = $type;
                $md = $file->getMetadata();
                $storagePath = Config::getStoragePath();

                foreach ($md as $key => $value) {
                    if ($key == 'MDATA_KEY_DIRECTORY' && !is_null($value)) {
                        $md['MDATA_KEY_FILEPATH'] = Application_Common_OsPath::join($storagePath, $md['MDATA_KEY_FILEPATH']);
                    }
                }

                $formatter = new SamplerateFormatter($md['MDATA_KEY_SAMPLERATE']);
                $md['MDATA_KEY_SAMPLERATE'] = $formatter->format();

                $formatter = new BitrateFormatter($md['MDATA_KEY_BITRATE']);
                $md['MDATA_KEY_BITRATE'] = $formatter->format();

                $formatter = new LengthFormatter($md['MDATA_KEY_DURATION']);
                $md['MDATA_KEY_DURATION'] = $formatter->format();

                $this->view->md = $md;
            } elseif ($type == 'playlist') {
                $file = new Application_Model_Playlist($id);
                $this->view->type = $type;
                $md = $file->getAllPLMetaData();

                $formatter = new LengthFormatter($md['dcterms:extent']);
                $md['dcterms:extent'] = $formatter->format();

                $this->view->md = $md;
                $this->view->contents = $file->getContents();
            } elseif ($type == 'block') {
                $block = new Application_Model_Block($id);
                $this->view->type = $type;
                $md = $block->getAllPLMetaData();

                $formatter = new LengthFormatter($md['dcterms:extent']);
                $md['dcterms:extent'] = $formatter->format();

                $this->view->md = $md;
                if ($block->isStatic()) {
                    $this->view->blType = 'Static';
                    $this->view->contents = $block->getContents();
                } else {
                    $this->view->blType = 'Dynamic';
                    $this->view->contents = $block->getCriteria();
                }
                $this->view->block = $block;
            } elseif ($type == 'stream') {
                $webstream = CcWebstreamQuery::create()->findPK($id);
                $ws = new Application_Model_Webstream($webstream);

                $md = $ws->getMetadata();

                $this->view->md = $md;
                $this->view->type = $type;
            }
        } catch (Exception $e) {
            Logging::info($e->getMessage());
        }
    }

    public function publishDialogAction()
    {
        $this->_helper->layout->disableLayout();
        // This just spits out publish-dialog.phtml!
    }
}